public class 父类A { int age = 10; protected void say() { System.out.println("父类A"); } public 父类A() { override(); } public void override() { System.out.println("父类A override"); } } class 子类B extends 父类A { int age = 9; private final Date date; public 子类B() { date = new Date(); } @Override public void override() { System.out.println(date); } @Override protected void say() { System.out.println("子类B"); } public static void main(String[] args) { 父类A b = new 子类B(); 子类B.override(); } }
注意一:java
在使用 new 来建立对象的时候,会先检查该类是否继承自父类,若是是,则会先调用父类的构造方法,该案例中,在 new 子类B() 时,发现 子类B 是 父类A 的子类,因而先调用 父类A 的构造方法,在 父类A 构造方法中,发现调用了 override 方法,因而又去寻找子类 子类B 是否重写了 override 方法,发现该子类重写了,则调用子类的 override,打印出 date,而此时 date 还未被初始化,因此值为 null。 在父类的构造方法执行完毕后,再执行子类的构造方法,此时 date 被初始化了,因此再次调用 override 方法时,则会正确打印出 date。ide
调用方法时,会优先在子类中寻找对应方法,若是子类中不存在,才会去调用父类中方法。code
注意二:对象
当调用 子类B.age,会打印出什么呢?是 10 仍是 9 ?继承
结果是打印出 10,建立对象的时候,实例变量有两种类型,前面是声明类型,后面是实际类型class
父类A b = new 子类B();
b 的声明类型为 父类A,实际类型为 子类B。变量
当调用成员变量的时候,会先在声明类型中寻找该变量,若是该变量存在,则使用声明类型中的变量值,若是不存在,则在实际类型中去寻找该变量。date
总结:方法
调用成员变量的时候,会先在声明类型中寻找该变量,若是该变量存在,则使用声明类型中的变量值,若是不存在,则在实际类型中去寻找该变量。总结
调用方法的时候,优先在子类中寻找对应方法,若是子类中不存在,再调用父类中方法。