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: 
 父类--静态变量
 父类--静态初始化块
 子类--静态变量
 子类--静态初始化块
 父类--变量
 父类--初始化块
 父类--构造器
 子类--变量
 子类--初始化块
 子类--构造器
*///:~
posted @ 2010-07-24 19:23  philander  阅读(314)  评论(0编辑  收藏  举报