super关键字
super表示父类引用
super(参数列表)表示调用父类构造方法,这一句必须放到子类构造方法的第一句。父类如果没有无参构造,子类必须显示调用父类的构造方法。
super.属性表示调用父类的属性,super.方法(参数列表)表示调用父类的方法。
注意:
super只能出现在子类构造方法和实例方法中。
super不能调用父类的私有属性和方法。
super和this的区别
调用方法
this访问本类中的方法,包括从父类中继承的方法。
super访问父类的方法。
调用构造方法
this(参数列表)表示调用本类的构造方法,必须放在本类构造方法的第一句。
super(参数列表)表示调用父类的构造方法,必须放在子类构造方法首行,如果表示调用父类的无参构造,super()可省略。super调用构造方法的语句不能和this调用本类构造方法的语句同时存在。
调用字段
this.字段:表示调用当前类的字段,包括从父类继承的。
super.字段:表示调用父类中的字段。
使用
this在实例方法中可以使用,static方法中不能使用,每个类都有this。
super在实例方法中可以使用,在static方法中不能使用,而且只能出现在子类中。
其他区别
this表示当前对象,super不能表示当前对象。
final关键字
final关键字用于修饰变量、方法和类。
修饰变量
final修饰的变量称为常量,一旦被初始化,就无法再被修改。常量必须在声明时或者构造函数中初始化,一般用大写字母和下划线组成。
修饰方法
被final修饰的方法不能被重写。
修饰类
被final修饰的类不能被继承。
Object类
在Java中所有类都直接或间接的继承了Object类,Object类是Java中的超级父类。
Object定义了大量的可以被其他类继承的类:
重写equals()方法可以让两个对象的内容相同时判定为相等。
重写hashcode()方法使得具有相同内容的对象具有相同的哈希码。
重写equals()和重写hashcode()方法的练习题
public class Person {
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(!(obj instanceof Person)){
return false;
}
Person otherPerson = (Person) obj;
return this.name.equals(otherPerson.name) && this.age == otherPerson.age;
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * age + result;
return result;
}
@Override
public String toString() {
return "Person{" + "name = " + name + "\t" + ",age = " + age + "}";
}
}
public class ObjectExample {
public static void main(String[] args) {
Person p1 = new Person("Alice",25);
Person p2 = new Person("Bob",30);
Person p3 = new Person("Alice",25);
System.out.println(p1.equals(p2));
System.out.println(p1.equals(p3));
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p3.hashCode());
System.out.println(p1.toString());
System.out.println(p2);
}
}
//输出结果
// false
// true
// 63351143
// 67895
// 63351143
// Person{name = Alice ,age = 25}
// Person{name = Bob ,age = 30}
注意:Object是java.lang包下的,使用时无需导包。Objects是java.util包下的,使用时需要导包(又是一个小细节)!
多态
方法重写是实现多态的基础。多态简单来说就是创建对象时变量引用的是哪个对象,就调用哪个对象的方法,例如:
Pet pet = new Dog();
pet.toHospital()就会调用Dog类中的toHospital()方法,而不是调用父类Pet中的toHospital()方法。
多态的表现形式:父类类型 对象名称 = 子类对象
实现多态的三个条件
子类继承父类并且重写父类的方法。
父类引用指向子类对象。
父类引用调用方法时,实际上调用的是子类的方法。
注意:
父类只能调用子类从父类中继承的方法或重写的方法,父类引用不能调用子类新增的方法。
向上转型
子类向父类转换成为向上转换,相当于基本数据类型中的自动类型提升。向上转型发生后,将无法调用子类新增的方法。
语法格式:父类类型 变量名 = new 子类类型();
向下转型
父类向子类转换,这时可以调用子类新增的方法,这就相当于基本数据类型中的强制类型转换。
语法格式:
子类类型 变量名 = (子类类型) 父类类型的引用变量
Dog dog = (Dog) pet;
dog.lookhouse();
此时就能调用子类新增的方法了。
instanceof运算符
在向下转型的过程中,如果不是转换为真实的子类类型,会出现类型转换异常。
例如:
Pet pet = new Dog(); //父类引用pet指向子类对象Dog
pet.toHospital(); //调用Dog类的toHospital方法
Bird bird = (bird) pet //将Dog类转换成Bird类会出错,因为此时的pet指向的是Dog类,而不是父类Pet
对于以上这种情况,Java提供了instanceof运算符进行类型转换的判断。
使用instanceof时对象的类型必须和instanceof后面的参数所指定的类有继承关系,否则会编译报错,例如pet instanceof String 。
在使用instanceof时先判断获取的pet对象是不是Dog类型,在做强制类型转换,然后再对pet对象进行操作。在java16的增强之后,instanceof的判断以及类型转换可以合二为一了。
if(pet instanceof Dog dog){ //判断pet执行的是否是Dog类
dog.lookHouse();
}
getClass方法
在Java中也可以使用getClass()来进行类型转换的判断。getClass()方法是Object类的一个方法,因此任何对象都可以调用它。
getClass()方法返回的是运行时类的Class对象,所有比较时用==运算符,而不能使用equals()方法。getClass()进行类型转换的判断通常用于处理特定类型的对象,在处理继承层次结构时,通常使用instanceof运算符来进行判断。