// 情況 1: 初始化塊在後 → 輸出 100
class Test1 {
int a = 10;
{ a = 100; } // 實例初始化塊
}
// 情況 2: 賦值在後 → 輸出 10
class Test2 {
{ a = 100; }
int a = 10;
}
Java 物件創建時,實例欄位初始化嚴格遵循源碼中出現的順序 (從上到下),然後才執行構造函數體。
第 5 步中,欄位聲明賦值 (`int a = 10`) 與實例初始化塊 (`{ a = 100; }`) 混合排序,誰在源碼下方誰後執行,後執行者覆蓋先前值。
// 情況 1 編譯後構造函數字節碼 (簡化)
0: aload_0
1: invokespecial #1 // Object.
4: aload_0
5: bipush 10
7: putfield #2 // a = 10 (欄位賦值)
10: aload_0
11: bipush 100
13: putfield #2 // a = 100 (初始化塊)
16: return
// 情況 2
0: aload_0
1: invokespecial #1
4: aload_0
5: bipush 100
7: putfield #2 // a = 100 (初始化塊)
10: aload_0
11: bipush 10
13: putfield #2 // a = 10 (欄位賦值)
16: return
字節碼明確顯示:編譯器按源碼順序線性化 所有欄位賦值與初始化塊到構造函數開頭 (super() 之後)。
class Parent { int x = 10; { x = 20; } Parent() { x = 30; } }
class Child extends Parent { int x = 40; { x = 50; } Child() { x = 60; } }
new Child(); // Child.x 最终 = 60, Parent.x = 30
父子類同名欄位不構成覆蓋,各自初始化鏈獨立執行,最終各自構造函數體賦值生效。