构造函数也是static方法,只是没有将static方法显性的显示出来。所以更准确来说,类是在其任何static成员被访问时加载。
创建子类对象时会先调用父类的构造函数 。因为子类的static初始化可能会依赖于父类成员能否被正确的初始化,所以需先完成父类的初始化(通过自动调用构造函数来完成父类成员属性的实例化和对成员方法的正确初始化)
①首先,等父类被加载完毕后,对象中所有的基本类型都会被设为默认值,对象引用被设为null–这是通过将对象内存设为二进制零值而一举生成的。
②随后,子类的构造器就会被调用,子类构造器完成之后,实例变量按其依次序被初始化
③最后,构造器其余部分被执行
以下借鉴博客园:Java父类调用被子类重写的方法
如果父类构造器调用了被子类重写的方法,且通过子类构造函数创建子类对象,调用了这个父类构造器(无论显示还是隐式),就会导致父类在构造时实际上调用的是子类覆盖的方法(你需要了解java继承中的初始化机制)。
例子:
public abstract class Father {
public Father() {
display();
}
public void display() {
System.out.println("Father's display");
}
}
public class Son extends Father {
public Son() {
}
public void display() {
System.out.println("Son's display");
}
public static void main(String[] args) {
new Son();
}
}
输出为:Son’s display
这种机制有优点,不过有时也存在问题。
优点: 通过继承相同的父类,初始化子类时,父类会调用不同子类的不同复写方法,从而实现多态性。
缺点: 如果在父类构造函数中调用被子类重写的方法,会导致子类重写的方法在子类构造器的所有代码之前执行,从而导致子类重写的方法访问不到子类实例变量的值,因为此时这些变量还没有被初始化。