在 Java 類別初始化的過程中,靜態區塊、實例區塊(非靜態區塊)以及建構子的執行順序常讓開發者感到困惑。本文將透過程式碼範例與執行結果,清晰解析三者的載入時機與呼叫順序,幫助你建立正確的觀念。
static { ... } 宣告,屬於類別層級,在類別被類別載入器載入時僅執行一次,優先於主方法與任何實例建立。{ ... } 宣告,屬於物件層級,在每次建立新物件時執行,且早於建構子。以下範例展示了父類別、子類別、靜態區塊、實例區塊與建構子混合時的完整執行流程:
public class ExecutionOrderDemo {
// 1. 父類別靜態區塊
static {
System.out.println("父類別:靜態區塊");
}
// 2. 父類別實例區塊
{
System.out.println("父類別:實例區塊");
}
// 3. 父類別建構子
public ExecutionOrderDemo() {
System.out.println("父類別:建構子");
}
// 4. 子類別靜態區塊
static class Child extends ExecutionOrderDemo {
static {
System.out.println("子類別:靜態區塊");
}
{
System.out.println("子類別:實例區塊");
}
public Child() {
System.out.println("子類別:建構子");
}
}
public static void main(String[] args) {
System.out.println("=== 主方法開始 ===");
new Child();
System.out.println("=== 建立第二個子類別實例 ===");
new Child();
}
}
父類別:靜態區塊
子類別:靜態區塊
=== 主方法開始 ===
父類別:實例區塊
父類別:建構子
子類別:實例區塊
子類別:建構子
=== 建立第二個子類別實例 ===
父類別:實例區塊
父類別:建構子
子類別:實例區塊
子類別:建構子
new 皆重複)。this 關鍵字)。掌握「靜態優先、父優於子、實例區塊早於建構子」這條主軸,即可輕鬆推導任何複雜繼承體系下的初始化順序。實務上,靜態區塊常用於載入原生庫或初始化單例;實例區塊則適合多建構子共用的初始化邏輯,避免程式碼重複。