標籤:執行 執行個體 void 初始化塊 執行順序 操作 處理 順序 []
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);//225 System.out.println(C.b);//126 System.out.println(new C().c);//227 System.out.println(new C().d);//128 System.out.println(new C().e);//329 }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);// 216 System.out.println(new C().a);// 317 System.out.println(C.b);// 018 }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);// 127 System.out.println(C.b);// 228 System.out.println(new C().c);// 229 System.out.println(new C().d);// 130 System.out.println(new C().e);// 231 System.out.println(new C().f);// 232 }33 }
Java初始化順序(靜態變數、靜態初始化塊、執行個體變數、執行個體初始化塊、構造方法)