java静态/动态成员变量、初始化块,父类/子类构造函数执行顺序问题

来源:互联网 发布:诸葛亮网络用语含义 编辑:程序博客网 时间:2024/04/30 11:19
  1. package job;  
  2.   
  3. public class TestConsSeq {  
  4.   
  5.     public static void main(String[] args) {  
  6.         /* 
  7.          * 几大原则 
  8.          * 一、静态成员变量(Static) 
  9.          *  1、静态成员变量为类变量,所有对象共享同一内存空间 
  10.          *  2、静态成员变量的声明和定义仅在首次加载类时执行一次 
  11.          *  3、首次加载类时首先对所有静态成员变量根据类型默认赋初值,然后再对有右值的附右值 
  12.          * 二、静态初始块 
  13.          *  1、静态初始化块仅在首次加载类时执行一次 
  14.          * ······多个静态成员变量与静态始化快参照出现顺序先后执行······ 
  15.          * 三、动态成员变量 
  16.          *  1、动态成员变量定义在每次实例化对象时在构造函数之前执行 
  17.          * 四、动态初始化块 
  18.          *  1、动态初始化块在每次实例化对象时在构造函数之前执行 
  19.          * ······多个动态成员变量与动态初始化块参照出现顺序先后执行······ 
  20.          * 总结:总的来说,在不涉及继承的前提下,当首次加载类时,按照如下顺序执行 
  21.          *  1、按照出现顺序先后执行静态成员变量定义与静态初始化块 
  22.          *  2、按照出现顺序先后执行动态成员变量定义与动态初始化块 
  23.          *  3、执行构造函数 
  24.          *  再次实例化对象时只执行第2、3步即可 
  25.          *  
  26.          * ············成员变量与定义与初始化块先于构造函数执行········· 
  27.          * 五、当涉及到继承时,按照如下顺序执行 
  28.          *  1、执行父类的静态成员变量定义与静态初始化块,执行子类的静态成员变量定义与静态初始化块 
  29.          *  2、执行父类的非静态成员变量定义与动态初始化块,执行父类构造方法 
  30.          *  3、执行子类的非静态成员变量定义与动态初始化块,执行子类构造方法 
  31.          * 另:父类构造方法中用到的方法如果已被子类重写,那么在构造子类对象时在调用父类构造函数中使用子类重写的方法 
  32.          */   
  33.         int i = 0;  
  34.         switch(i) {  
  35.         case 0:  
  36.               
  37.             new A();  
  38.             new A();  
  39.               
  40.             break;  
  41.         case 1:  
  42.               
  43.             A ab = new B();  
  44.               
  45.             break;  
  46.         case 2 :  
  47.               
  48.             C c1 = new C();  
  49.             System.out.println("c.i1 = " + c1.i1);//2  
  50.             System.out.println("c.i2 = " + c1.i2);//3  
  51.               
  52.             break;  
  53.         }   
  54.         /* 对i=2时的解释 
  55.          * 为什么是2和3呢? 
  56.          * 其实代码的执行顺序是这样的:在初始化c1的时候首先加载类 
  57.          * 定义静态变量t1,i1,i2并赋初值null,0,0 
  58.          * 然后计算右值表达式new C(),准备将此对象赋给静态成员变量c 
  59.          *      然而上步中静态成员变量已定义,直接执行c的构造函数即可 
  60.          *      这样i1++,i2++被执行,i1,i2都变为1 
  61.          * 继续执行到int i1;没有赋值语句, i1,i2的值仍然是1 
  62.          * 继续执行到int i2 = 2时i2被赋值2,即i1 = 1,i2 = 2 
  63.          * 继续执行到c1的构造函数,i1,i2再执行++,此时i1 = 2,i2 = 3 
  64.          * 输出i1,i2,结果就是:c1.i1 = 2,c1.i2 = 3 
  65.          * 通过上面的代码我们可以认为系统默认值的给予比通过等号的赋予先执行。 
  66.          */  
  67.     }  
  68. }  
  69.   
  70. class A {  
  71.     public A() {  
  72.         System.out.println("construct A");  
  73.         m();  
  74.         System.out.println();  
  75.     }  
  76.       
  77.     private int ai = getAI();  
  78.       
  79.     {  
  80.         System.out.println("dynamic block in A");  
  81.     }  
  82.   
  83.     static {  
  84.         System.out.println("static block in A");  
  85.     }  
  86.       
  87.     private static int asi = getASI();  
  88.       
  89.     static int getASI() {  
  90.         System.out.println("initial static int asi");  
  91.         System.out.println();  
  92.         return 5;  
  93.     }  
  94.       
  95.     static int getAI() {  
  96.         System.out.println("initial int ai");  
  97.         return 10;  
  98.     }  
  99.       
  100.     public void m() {  
  101.         System.out.println("A.m()");  
  102.     }  
  103. }  
  104.   
  105. class B extends A{  
  106.     public B() {  
  107.         System.out.println("construct B");  
  108.         super.m();  
  109.         m();  
  110.     }  
  111.       
  112.     {  
  113.         System.out.println("dynamic block in B");     
  114.     }  
  115.     private int bi = getBI();  
  116.     private static int bsi = getBSI();  
  117.   
  118.       
  119.     static {  
  120.         System.out.println("static block in B");  
  121.         System.out.println();  
  122.     }  
  123.       
  124.     static int getBSI() {  
  125.         System.out.println("initial static int bsi");  
  126.         return 5;  
  127.     }  
  128.       
  129.     static int getBI() {  
  130.         System.out.println("initial int bi");  
  131.         return 10;  
  132.     }  
  133.       
  134.     public void m() {  
  135.         System.out.println("B.m() bi=" + bi);  
  136.     }  
  137. }  
  138.   
  139. class C{  
  140.     private static C c = new C();  
  141.     public static int i1;  
  142.     public static int i2 = 2;  
  143.       
  144.     public C(){  
  145.         i1++;  
  146.         i2++;  
  147.     }  
  148. }  

i=0时输出:

[plain] view plaincopy
  1. static block in A  
  2. initial static int asi  
  3.   
  4. initial int ai  
  5. dynamic block in A  
  6. construct A  
  7. A.m()  
  8.   
  9. initial int ai  
  10. dynamic block in A  
  11. construct A  
  12. A.m()  

i=1时输出:

[plain] view plaincopy
  1. static block in A  
  2. initial static int asi  
  3.   
  4. initial static int bsi  
  5. static block in B  
  6.   
  7. initial int ai  
  8. dynamic block in A  
  9. construct A  
  10. B.m() bi=0  
  11.   
  12. dynamic block in B  
  13. initial int bi  
  14. construct B  
  15. A.m()  
  16. B.m() bi=10  

i=2时输出

[plain] view plaincopy
  1. c.i1 = 2  
原创粉丝点击