先说结论
对于具备继承关系的类,它们的类和对象构造顺序为:父类的类构造器() -> 子类的类构造器() -> 父类成员变量的赋值和实例代码块 -> 父类的构造函数 -> 子类成员变量的赋值和实例代码块 -> 子类的构造函数。函数
实验代码以下:code
public class ExtensionTest { public static void main(String[] args) { new SubClass(); } } class SuperClass { { System.out.println("我是父类实例块"); } static { System.out.println("我是父类类构造块"); } public SuperClass() { System.out.println("我是父类构造函数块"); } } class SubClass extends SuperClass { { System.out.println("我是子类实例块"); } static { System.out.println("我是子类类构造块"); } public SubClass() { System.out.println("我是子类构造函数块"); } }
结果:对象
我是父类类构造块
我是子类类构造块
我是父类实例块
我是父类构造函数块
我是子类实例块
我是子类构造函数块继承
解释:
类构造块是初始化类的时候执行的,而初始化类首先得加载类(不加载类进内存固然无法初始化)。
类实例块是放在该类构造函数最前面和父类构造函数以后执行的。由于子类的构造函数调用以前,会先调用父类的构造函数。内存
基于上述两条规则,咱们再来看执行顺序。
new SubClass()也就是要构造SubClass这个类的一个对象,而要构造这个对象,首先必须把这个类的描述、定义加载进内存(类加载)。所以要先加载这个类(不过此时还未初始化)。
加载完这个类以后,想要构造这个类的对象。可是此时这个类的静态变量还未被初始化,所以要先初始化这个类,可是初始化这个类须要先初始化它的父类,所以此时就变成了,加载父类->初始化父类(调用静态块,即类构造块)
->初始化子类(调用静态块,即类构造块)。
而后就能够构造这个类的对象了,构造这个类的对象以前,要先构造父类对象,所以会先调用父类的构造函数,而调用父类构造函数以前又会先调用父类的实例块。
而后就到了子类构造函数,然而执行以前同样要先调用子类的实例块,最后才是子类的构造函数的函数体。io