黑马程序员技术交流社区

标题: 执行顺序问题 [打印本页]

作者: hejinzhong    时间: 2014-9-6 22:43
标题: 执行顺序问题
java静态/动态成员变量、初始化块,父类/子类构造函数执行顺序问题


  1. package job;

  2. public class TestConsSeq {

  3.         public static void main(String[] args) {
  4.                 /*
  5.                  * 几大原则
  6.                  * 一、静态成员变量(Static)
  7.                  *         1、静态成员变量为类变量,所有对象共享同一内存空间
  8.                  *         2、静态成员变量的声明和定义仅在首次加载类时执行一次
  9.                  *         3、首次加载类时首先对所有静态成员变量根据类型默认赋初值,然后再对有右值的附右值
  10.                  * 二、静态初始块
  11.                  *         1、静态初始化块仅在首次加载类时执行一次
  12.                  * ······多个静态成员变量与静态始化快参照出现顺序先后执行······
  13.                  * 三、动态成员变量
  14.                  *         1、动态成员变量定义在每次实例化对象时在构造函数之前执行
  15.                  * 四、动态初始化块
  16.                  *         1、动态初始化块在每次实例化对象时在构造函数之前执行
  17.                  * ······多个动态成员变量与动态初始化块参照出现顺序先后执行······
  18.                  * 总结:总的来说,在不涉及继承的前提下,当首次加载类时,按照如下顺序执行
  19.                  *         1、按照出现顺序先后执行静态成员变量定义与静态初始化块
  20.                  *         2、按照出现顺序先后执行动态成员变量定义与动态初始化块
  21.                  *         3、执行构造函数
  22.                  *         再次实例化对象时只执行第2、3步即可
  23.                  *
  24.                  * ············成员变量与定义与初始化块先于构造函数执行·········
  25.                  * 五、当涉及到继承时,按照如下顺序执行
  26.                  *         1、执行父类的静态成员变量定义与静态初始化块,执行子类的静态成员变量定义与静态初始化块
  27.                  *         2、执行父类的非静态成员变量定义与动态初始化块,执行父类构造方法
  28.                  *         3、执行子类的非静态成员变量定义与动态初始化块,执行子类构造方法
  29.                  * 另:父类构造方法中用到的方法如果已被子类重写,那么在构造子类对象时在调用父类构造函数中使用子类重写的方法
  30.                  */       
  31.                 int i = 0;
  32.                 switch(i) {
  33.                 case 0:
  34.                        
  35.                         new A();
  36.                         new A();
  37.                        
  38.                         break;
  39.                 case 1:
  40.                        
  41.                         A ab = new B();
  42.                        
  43.                         break;
  44.                 case 2 :
  45.                        
  46.                         C c1 = new C();
  47.                         System.out.println("c.i1 = " + c1.i1);//2
  48.                         System.out.println("c.i2 = " + c1.i2);//3
  49.                        
  50.                         break;
  51.                 }
  52.         /* 对i=2时的解释
  53.          * 为什么是2和3呢?
  54.          * 其实代码的执行顺序是这样的:在初始化c1的时候首先加载类
  55.          * 定义静态变量t1,i1,i2并赋初值null,0,0
  56.          * 然后计算右值表达式new C(),准备将此对象赋给静态成员变量c
  57.          *                 然而上步中静态成员变量已定义,直接执行c的构造函数即可
  58.          *                 这样i1++,i2++被执行,i1,i2都变为1
  59.          * 继续执行到int i1;没有赋值语句, i1,i2的值仍然是1
  60.          * 继续执行到int i2 = 2时i2被赋值2,即i1 = 1,i2 = 2
  61.          * 继续执行到c1的构造函数,i1,i2再执行++,此时i1 = 2,i2 = 3
  62.          * 输出i1,i2,结果就是:c1.i1 = 2,c1.i2 = 3
  63.          * 通过上面的代码我们可以认为系统默认值的给予比通过等号的赋予先执行。
  64.          */
  65.         }
  66. }

  67. class A {
  68.         public A() {
  69.                 System.out.println("construct A");
  70.                 m();
  71.                 System.out.println();
  72.         }
  73.        
  74.         private int ai = getAI();
  75.        
  76.         {
  77.                 System.out.println("dynamic block in A");
  78.         }

  79.         static {
  80.                 System.out.println("static block in A");
  81.         }
  82.        
  83.         private static int asi = getASI();
  84.        
  85.         static int getASI() {
  86.                 System.out.println("initial static int asi");
  87.                 System.out.println();
  88.                 return 5;
  89.         }
  90.        
  91.         static int getAI() {
  92.                 System.out.println("initial int ai");
  93.                 return 10;
  94.         }
  95.        
  96.         public void m() {
  97.                 System.out.println("A.m()");
  98.         }
  99. }

  100. class B extends A{
  101.         public B() {
  102.                 System.out.println("construct B");
  103.                 super.m();
  104.                 m();
  105.         }
  106.        
  107.         {
  108.                 System.out.println("dynamic block in B");       
  109.         }
  110.         private int bi = getBI();
  111.         private static int bsi = getBSI();

  112.        
  113.         static {
  114.                 System.out.println("static block in B");
  115.                 System.out.println();
  116.         }
  117.        
  118.         static int getBSI() {
  119.                 System.out.println("initial static int bsi");
  120.                 return 5;
  121.         }
  122.        
  123.         static int getBI() {
  124.                 System.out.println("initial int bi");
  125.                 return 10;
  126.         }
  127.        
  128.         public void m() {
  129.                 System.out.println("B.m() bi=" + bi);
  130.         }
  131. }

  132. class C{
  133.     private static C c = new C();
  134.     public static int i1;
  135.     public static int i2 = 2;
  136.    
  137.     public C(){
  138.         i1++;
  139.         i2++;
  140.     }
  141. }

  142. /*  i=0时
  143. static block in A
  144. initial static int asi

  145. initial int ai
  146. dynamic block in A
  147. construct A
  148. A.m()

  149. initial int ai
  150. dynamic block in A
  151. construct A
  152. A.m()

  153. //  i=1 时

  154. static block in A
  155. initial static int asi

  156. initial static int bsi
  157. static block in B

  158. initial int ai
  159. dynamic block in A
  160. construct A
  161. B.m() bi=0

  162. dynamic block in B
  163. initial int bi
  164. construct B
  165. A.m()
  166. B.m() bi=10

  167. //  i=2时
  168. c.i1 = 2
  169. c.i2 = 3

复制代码






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2