static同构造函数的执行顺序

例1:
abstract   class  Glyph {
2       Glyph() {
3             System.out.println( " Glyph() before draw() " );
4             draw();  // 不明白的地方是这里.
5            System.out.println( " Glyph() after draw() " );
6        }
7     abstract   void  draw();
8  }

10   class  RoundGlyph  extends  Glyph {
11     private   int  radius  =   1 ;
12     RoundGlyph( int  r) {
13         radius  =  r;
14         System.out.println( " RoundGlyph.RoundGlyph(), radius =  "   +  radius);
15     }
16
17    void  draw() {
18       // radius = z;
19         System.out.println( " RoundGlyph.draw(), radius =  "   +  radius);
20    }
21  }
22 
23   public   class  PolyConstructors {
24      public   static   void  main(String[] args) {
25              new  RoundGlyph( 5 );
26        }
27  }

答案:
1  Glyph() before draw()
2  RoundGlyph.draw(), radius  =   0
3  Glyph() after draw()
4  RoundGlyph.RoundGlyph(), radius  =   5
分析:分析
1类初始化时构造函数调用顺序:
2 首先加载类,遇到extends字样会停止加载当前类,加载父类,之后再继续加载。
3 当把一个类完全加载后,这个类的静态成员将被先加载。之后进行如下流程:
4(1)初始化对象的存储空间为零或null值;
5(2)调用父类构造函数;
6(3)按顺序分别调用类成员变量和实例成员变量的初始化表达式;
7(4)调用本身构造函数

9构造函数的初始化顺序:
101 .当执行new RoundGlyph( 5 )时,首先会加载‘RoundGlyph. class ’,但是这个时候JVM发现 RoundGlyph  extends (继承于) Glyph ,所以他会加载Glyph. class
112 .然后会初始化Glyph类的static成员数据,这个类没有static成员数据,所以没有这一步。
123 .会执行Glyph类的构造函数Glyph()
134 .接着初始化RoundGlyph类的成员数据,最后调用RoundGlyph()构造函数来生产对象
例2:
1public   class  Test2  extends  Test1  {
2    {
3         System.out.print( "  1  " );
4    }
5    Test2()  {
6         System.out.print( "  2  " );
7    }
8    static   {
9        System.out.print( "  3  " );
10    }
11    {
12        System.out.print( "  4  " );
13    }
14     public   static   void  main(String[] args)  {
15         new  Test2();
16     }
17}
18
19class  Test1  {
20    Test1()  {
21        System.out.print( "  5  " );
22    }
23    static   {
24        System.out.print( "  6  " );
25    }
26}
答案:635142
解析: 1( 1 ) 虚拟机试图加载Test2,其父类为Test1
2 ( 2 ) 虚拟机加载Test1
3 ( 3 ) Test1静态初始化  ----->  输出 " 6 "
4 ( 4 ) 虚拟机加载Test2
5 ( 3 ) Test2静态初始化  ----->  输出 " 3 "
6 ( 5 )  new  Test2()构造Test2首先构造父类Test1
7 ( 6 ) Test1构造  ----->  输出 " 5 "
8 ( 7 ) Test2执行初始化语句块(虚拟机调用Test2初始化方法init)  ----->  输出 " 1 " 和 " 4 "
9 ( 8 ) Test2构造  ----->  输出 " 2 "
10
11 =================================
12 先输出6:
13 因为父类的Static的变量 / 常量会被子类共享
14 所以,首先输出6
15 接着,会先初始化自身的static的变量 / 常量
16
17 然后,在构造函数中,会首先调用父类的默认构造函数(如果没有显示调用super(args)的话)
18 在调用父类构造函数时,在执行构造函数体中的数据内容时,先执行方法外的程序段,如变量申明,或者程序段。然后再调用构造函数中的程序段。
19 然后再执行自身的构造函数,执行前,也如上述说:在执行本构造函数体中的数据内容时,先执行方法外的程序段,如变量申明,或者程序段。然后再调用构造函数中的程序段。
20
21 这就是一个对象的实例化过程。


你可能感兴趣的:(jvm,虚拟机)