继承是Java程序设计的一项核心技术。
一、子类构造器
因为子类的构造器不能访问超类的私有域,所以必须利用超类的构造器对这部分私有域进行初始化。可以通过super实现对超类构造器的调用。
二、this和supper的用法
关键词this有两个用途:①引用隐式参数;②调用该类其他构造器。
关键词supper也有两个用途:①调用超类的方法;②调用超类的构造器。
在调用构造器的时候,调用构造器的语句都只能作为另一个构造器的第一条语句出现。构造器参数既可以传递给本类(this)的其他构造器,也可以传递给超类(supper)的构造器。
三、多态和动态绑定
一个对象变量可以指示多种实际类型的现被称为多态;
例如,Manage继承的Employee,Employee的对象e既可以指示Manage,又可以指示Employee。
在运行时能够自动地选择调用哪种方法的现象称为动态绑定。
例如,在运行的时候,e可能调用的是Employee的getSalary()方法,也可能调用的是Manage的getSalary()方法。
四、继承后,方法覆盖的返回类型
方法的名字和参数列表称为方法的签名。
允许子类将覆盖方法的返回类型定义为原返回类型的子类型。
例如:
// 超类的方法
public Employee getBuddy(){...}
//子类覆盖超类的方法
public Manager getBuddy(){...}
五、覆盖的注意事项
在覆盖一个方法的时候,子类的方法不能低于超类方法的可见性。
六、final修饰符修饰类
如果将一个类声明为final,只有其中的方法自动地成为final,而不包括域。
七、Object:所有类的超类
7.1 equals() 方法
在Object类中,这个方法将判断两个对象是否具有相同的引用。如果要通过比较两个对象的状态是否相同,来判断这两个对象是否相等,就要再Object类的子类中覆盖equals方法。
在比较 name.equals(other.name) 时候,为了防备name可能为null的情况,需要使用Object.equals 方法。如果两个参数都为null,Objects.equals(a,b) 调用将返回true;如果其中一个参数为null,则返回false;否则,如果两个参数都不相等,则调用a.equals(b)。
7.2 编写一个完美的equals方法:
(重新定义了equals方法,就一定要重新定义hashCode方法)
1) 显示参数命名为otherObject,稍后需要将其转化为一个叫other的变量;
2)检测this与otherObject是否引用同一个对象:
if(this == otherObject) return true;
3) 检测otherObject是否为null,如果为null,返回false
if(otherOjbect == null) return false;
4) 比较this与otherObject是否属于同一个类。
如果equals的语义在每个子类中有所改变,就使用getClass 检测:
if(getClass() != otherObject.getClass()) return false;
如果所有的子类都拥有统一的语义,就使用instanceof 检测
if(!(otherObject instanceof ClassName)) return false;
5) 将otherObject转换为相应的类类型变量:
ClassName other = (ClassName)otherObject;
6)开始对所需要比较的域进行比较。基本类型域使用 ==, 对象域使用 equals比较
return field1 == other.field1 && Objects.equals(field2,other.field2) &&...;
7.2 hashCode 方法
Object类的默认 hashCode() 方法导出对象的存储地址。
如果重新定义equals方法,就必须重新定义hashCode方法,以便用户可以将对象插入到散列表中。
name.hashCode()。
为了使用null安全的方法,可以使用 Objects.hashCode 如果参数为null,则返回0。
Objects.hash 可以提供多个参数。
7.3 toString 方法
Object中的toString 方法,用于返回表示对象值的字符串。
只要对象与一个字符串通过“+”连接起来,Java编辑就会自动调用toString方法,以便获得这个对象字符串的描述。
如果x是任意一个对象,并调用System.out.println(x); println方法就会直接调用x.toString(),并打印输出得到的字符串。
强烈建议为自定义的每一个类增加toString方法。