Code Analysis(2)之继承与构造器执行顺序
Create two classes, A and B, with default constructors (empty argument lists) that announce themselves. Inherit a new class called C from A, and create a member of class B inside C. Do not create a constructor for C. Create an object of class C and observe the resluts.
class A { A(){ println("A() " + this);} } class B extends A { B(){ System.out.println("B() " + this);} } class D extends A { B b1 = new B(); D(){ System.out.println("D() " + this);} } class C extends A { D d = new D(); public static void main(String[] args) { C c = new C(); // will construct an A first } } /* Output: A() C@a90653 A() D@1fb8ee3 A() B@61de33 B() B@61de33 D() D@1fb8ee3 *///:~
这个例子可以看出,程序的执行顺序:
I. 调用C的构造器,输出“A() C@a90653 ”;
II. 调用D的构造器,输出“A() D@1fb8ee3 ”(为什么不是接着就输出“D() D@1fb8ee3 ”呢?);
III. 创建B对象实例b1,调用B的构造器,输出:“A() B@61de33 B() B@61de33”
IV. 输出“D() D@1fb8ee3 ”
想来想去,觉得上面的解释不对。在initiailization中讲到:“在类的内部,定义变量的先后顺序决定了初始化的顺序。即变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。”所以应该这么解释:
首先,初始化C,调用其基类构造器,输出“A() C@a90653 ”;然后,初始化变量d,仍旧先调用其基类构造器,输出“A() D@1fb8ee3”;接着,初始化D中的变量b1,于是先调用其基类构造器,输出“A() B@61de33”,然后调用B本身的构造器B(),输出“B() B@61de33 ”;再接着,调用D本身的构造器D(),输出“D() D@1fb8ee3”;最后,调用C本身构造器C()(这里没有显示定义C的构造器,所以没有任何输出)
但是,为什么基类的构造器会在每个子类初始化的第一步执行呢?
于是在网上找了个构造器执行顺序:
I. 父类的静态成员赋值和静态块
II. 子类的静态成员和静态块
III. 父类的构造方法
IV. 父类的成员赋值和初始化块
V. 父类的构造方法中的其它语句
VI. 子类的成员赋值和初始化块
VII. 子类的构造方法中的其它语句
为了理解的更清晰些,在Javaeye上找到了个例子,只要看完这个例子就明白了:
1) 单个类中的静态变量、变量以及构造函数的初始化顺序
public class SingleInitialOrder { public static String staticField = "静态变量"; public String field = "变量"; static { System.out.println(staticField); System.out.println("静态初始化块"); } { System.out.println(field); System.out.println("初始化块"); } public SingleInitialOrder() { System.out.println("构造器"); } public static void main(String[] args) { new SingleInitialOrder(); } }/* Output: 静态变量 静态初始化块 变量 初始化块 构造器 *///:~
2) 子类和父类中静态变量、变量以及构造函数的初始化顺序
public class ParentChildInitialOrder extends Parent { public static String s_StaticField = "子类--静态变量"; public String s_Field = "子类--变量"; static { System.out.println(s_StaticField); System.out.println("子类--静态初始化块"); } { System.out.println(s_Field); System.out.println("子类--初始化块"); } public ParentChildInitialOrder() { System.out.println("子类--构造器"); } public static void main(String[] args) { new ParentChildInitialOrder(); } } class Parent { public static String p_StaticField = "父类--静态变量"; public String p_Field = "父类--变量"; static { System.out.println(p_StaticField); System.out.println("父类--静态初始化块"); } { System.out.println(p_Field); System.out.println("父类--初始化块"); } public Parent() { System.out.println("父类--构造器"); } } /* Output: 父类--静态变量 父类--静态初始化块 子类--静态变量 子类--静态初始化块 父类--变量 父类--初始化块 父类--构造器 子类--变量 子类--初始化块 子类--构造器 *///:~