1. 程式人生 > >Java初始化順序(靜態變量、靜態初始化塊、實例變量、實例初始化塊、構造方法)

Java初始化順序(靜態變量、靜態初始化塊、實例變量、實例初始化塊、構造方法)

靜態初始化 都對 class block 註釋 執行順序 blog 中一 成員變量

1、執行順序

1.1、一個類中的初始化順序

(靜態變量、靜態初始化塊)=>(變量、初始化塊、構造器)。

1.2、兩個具有繼承關系類的初始化順序

父類的(靜態變量、靜態初始化塊)=> 子類的(靜態變量、靜態初始化塊)=> 父類的(變量、初始化塊、構造器)=> 子類的(變量、初始化塊、構造器)。

示例如下:(結果見註釋)

 1 class A {
 2     public A() {
 3         System.out.println("Constructor A.");
 4     }
 5 
 6     {
 7         System.out.println("Instance Block A.");
8 } 9 static { 10 System.out.println("Static Block A."); 11 } 12 13 public static void main(String[] args) { 14 new A();/* 15 * Static Block A. Instance Block A. Constructor A. 16 */ 17 } 18 } 19 20 class B extends A {
21 public B() { 22 System.out.println("Constructor B."); 23 } 24 25 { 26 System.out.println("Instance Block B."); 27 } 28 static { 29 System.out.println("Static Block B."); 30 } 31 32 public static void main(String[] args) { 33 new
A();/* 34 * Static Block A. Static Block B. Instance Block A. Constructor A. 35 */ 36 System.out.println(); 37 new B();/* 38 * Instance Block A. Constructor A. Instance Block B. Constructor B. 39 */// 靜態成員和靜態初始化塊只會執行一次。 40 } 41 }

2、對變量值的影響

2.1、問題

Java中一個變量的初始化與初始化塊對該變量的賦值同時存在時變量的最終值如何確定?特別是初始化塊在變量定義之前甚至靜態初始化塊和實例初始化塊都對該變量進行賦值時更迷惑人。如對於如下示例,輸出的值分別為多少?(已給出):

 1 class C {
 2 
 3     static {
 4         a = 2;
 5         b = 2;
 6     }
 7     static int a;
 8     static int b = 1;
 9 
10     public C() {
11         e = 3;
12     }
13 
14     {
15         c = 2;
16         d = 2;
17         e = 2;
18     }
19     int c;
20     int d = 1;
21     int e = 1;
22 
23     public static void main(String[] args) {
24         System.out.println(C.a);//2
25         System.out.println(C.b);//1
26         System.out.println(new C().c);//2
27         System.out.println(new C().d);//1
28         System.out.println(new C().e);//3
29     }

2.2、分析

成員變量(類變量、實例變量)的 初始化塊賦值 及 變量定義 同時存在時變量的值的確定。包含如下幾種情況:

情況1、靜態變量定義 及 靜態初始化塊改變該變量值 同時存在時變量的最終值。

情況2、實例變量定義 及 實例初始化塊改變該變量 同時存在時變量的最終值。

情況3、或上述兩種同時改變一個變量 時變量的最終值。

若初始化塊在變量定義之後,則易知值為初始化塊裏的賦值,因此這裏考慮若初始化塊在變量定義之前的情形

2.3、結論

(考慮 對變量賦值的初始化塊在變量定義之前 的情形)

1、對於靜態操作和實例操作同時存在的情況(情況3),根據上節所述的執行順序確定值;

2、若定義變量時未顯式初始化,則成員變量會被默認初始化,進一步地若存在初始化塊則變量的值為初始化塊的賦值。如:

 1 class C {
 2     public C() {
 3     }
 4 
 5     {
 6         a = 3;
 7     }
 8     static {
 9         a = 2;
10     }
11     static int a;
12     static int b;
13 
14     public static void main(String[] args) {
15         System.out.println(C.a);// 2
16         System.out.println(new C().a);// 3
17         System.out.println(C.b);// 0
18     }
19 }

3、若定義時顯示地初始化了,即情況1、2,其處理方法一樣:

變量定義時進行顯式初始化實際上內部隱含 定義及初始化塊對之進行賦值 兩個過程,因此若還包含初始化塊代碼,則Java會將它們合並成一個處理,所以結論是顯式初始化和初始化塊哪個在後值就是哪個。如:

 1 class C {
 2     // 以下關於靜態初始化的
 3     static {
 4         a = 2;
 5     }
 6     static int a = 1;
 7     static int b = 1;
 8     static {
 9         b = 2;
10         c = 2;
11     }
12     static int c;
13 
14     {
15         d = 2;
16     }
17     int d = 1;
18     int e = 1;
19     {
20         e = 2;
21         f = 2;
22     }
23     int f;
24 
25     public static void main(String[] args) {
26         System.out.println(C.a);// 1
27         System.out.println(C.b);// 2
28         System.out.println(new C().c);// 2
29         System.out.println(new C().d);// 1
30         System.out.println(new C().e);// 2
31         System.out.println(new C().f);// 2
32     }
33 }

Java初始化順序(靜態變量、靜態初始化塊、實例變量、實例初始化塊、構造方法)