理解 Java 類初始化順序對於除錯繼承體系、解決循環依賴、掌握單例模式執行時機至關重要。本文結合程式碼範例與 JVM 載入機制,完整梳理父子類從載入到實例化的完整流程。
public class TestInit {
@Test
public void test() {
Child child = new Child();
}
}
class Parent {
public static String staticField = "父類靜態變數";
public String instanceField = "父類實例變數";
static { System.out.println(staticField); System.out.println("父類靜態塊"); }
{ System.out.println(instanceField); System.out.println("父類實例塊"); }
public Parent() { System.out.println("父類建構子"); }
}
class Child extends Parent {
public static String staticField = "子類靜態變數";
public String instanceField = "子類實例變數";
static { System.out.println(staticField); System.out.println("子類靜態塊"); }
{ System.out.println(instanceField); System.out.println("子類實例塊"); }
public Child() { System.out.println("子類建構子"); }
}
父類靜態變數
父類靜態塊
子類靜態變數
子類靜態塊
父類實例變數
父類實例塊
父類建構子
子類實例變數
子類實例塊
子類建構子
new Child 觸發類載入器尋找 Child.class,發現繼承 Parent,遞歸載入父類(無論是否建立父類實例)。Child 物件記憶體。super(...),隱式呼叫 super()。靜態先行,父前子後;實例跟著建構走,父建構完再輪到子。
ExceptionInInitializerError。init() 明確初始化。掌握初始化順序,能讓您在設計繼承體系、排查啟動異常時更有底氣,寫出更可預測的 Java 程式碼。