话不多说,先上代码
class Base {private String name = "base";public Base() {tellName();printName();}public void tellName() {System.out.println("Base tell name: " + name);}public void printName() {System.out.println("Base print name: " + name);}
}
class Dervied extends Base {private String name = "dervied";public Dervied() {tellName();printName();}public void tellName() {System.out.println("Dervied tell name: " + name);}public void printName() {System.out.println("Dervied print name: " + name);}public static void main(String[] args){new Dervied();}
}
运行结果是:
Dervied tell name: null
Dervied print name: null
Dervied tell name: dervied
Dervied print name: dervied
为什么会出现这样的输出结果呢?
知识点1:构造方法。当子类的构造方法不显式调用父类的构造方法时,会默认调用父类的无参构造方法。因此在new Dervied()时,会调用public Base()方法。
知识点2:方法重写(覆盖)。当调用Base的构造方法时,会调用tellName()和printName(),然而这两个方法已经在子类中重写,所以会调用Dervied类中的同名方法。然而这个时候,子类还没有实例化,那么实例变量也没有初始化,所以name = null;所以会输出Dervied tell name: null和Dervied print name: null。之后会正常调用子类构造方法,完成对象的创建。
知识点3:代码执行顺序。父类静态块→子类静态块→父类初始化块(成员变量,非静态代码块等)→父类构造方法→子类初始化块(成员变量,非静态代码块等)→子类构造方法。