Java 類別初始化順序是面試高頻考點:`static` 區塊 → `main` → 父類構造器 → 子類構造器。本文用一個包含繼承、靜態區塊、構造器的完整例子,逐步拆解 JVM 執行流程,並修正原始代碼中的語法錯誤。
class StaticSuper {
static {
System.out.println("super static block");
}
StaticSuper() { // 構造器,無返回類型,名稱與類同
System.out.println("super constructor");
}
}
public class StaticTests extends StaticSuper {
static int rand;
static {
rand = (int) (Math.random() * 6);
System.out.println("static block " + rand);
}
StaticTests() { // 子類構造器
System.out.println("constructor");
}
public static void main(String[] args) {
System.out.println("in main");
StaticTests st = new StaticTests();
}
}
super static block // 1. 父類靜態區塊 (類加載時)
static block 3 // 2. 子類靜態區塊 (類加載時,rand 隨機值)
in main // 3. main 方法開始
super constructor // 4. 父類構造器 (new 子類前隱式 super())
constructor // 5. 子類構造器
| 規則 | 說明 |
|---|---|
| 靜態區塊/靜態欄位 | 類加載時執行,**父類先於子類**,只執行一次 |
| 實例初始化區塊 `{ }` | 每次 `new` 時執行,**父類先於子類**,在構造器之前 |
| 構造器 | 每次 `new` 時執行,**父類構造器先於子類構造器** (隱式/顯式 `super()`) |
| main 方法 | 在所有靜態初始化完成**後**執行 |
| 構造器語法 | **無返回類型**、**名稱與類同**、**可帶參數**,非方法 |
class Parent {
{ System.out.println("Parent instance block"); } // 實例區塊
Parent() { System.out.println("Parent constructor"); }
}
class Child extends Parent {
{ System.out.println("Child instance block"); }
Child() { System.out.println("Child constructor"); }
}
// new Child() 輸出:
// Parent instance block
// Parent constructor
// Child instance block
// Child constructor
**靜態 (父→子) → main → 實例 (父→子:區塊→構造器)**。構造器不是方法,沒有返回類型,名稱必須與類同。掌握這條主線,繼承初始化順序題目秒殺。