首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 構造器鏈與對象初始化順序完全指南

     編輯:Java 相關知識

繼承鏈中的構造器調用規則

創建子類對象時,父類構造器總先於子類構造器執行。若父類無無參構造器,子類必須在構造器首行顯式調用 super(參數) 指定父類構造器,否則編譯失敗。

兩種解決方案對比

// 方案1:父類添加無參構造器
class Super { Super() {} }

// 方案2:子類顯式調用 super(str)
class Sub extends Super {
    Sub(String str) { super(str); /* ... */ }
}

方案 1 只輸出子類信息;方案 2 輸出父類再子類信息。本質區別在於是否執行父類初始化邏輯。

對象初始化完整順序

創建對象時,JVM 按以下順序執行:

  1. 父類靜態成員/靜態塊(按聲明順序,僅類加載時執行一次)
  2. 子類靜態成員/靜態塊
  3. 父類非靜態成員/實例塊(按聲明順序)
  4. 父類構造器
  5. 子類非靜態成員/實例塊
  6. 子類構造器

關鍵驗證案例

class Two {
    One one_1 = new One("one-1");  // 非靜態成員
    static One one_3 = new One("one-3"); // 靜態成員
    Two(String s) { System.out.println(s); }
}

public class Test {
    static Two two_3 = new Two("two-3"); // 主類靜態成員
    public static void main(String[] args) {
        System.out.println("main start");
        new Two("two-1");
        new Two("two-2");
    }
}

輸出順序:

one-3        // 類 Two 靜態成員(最先,僅一次)
one-1        // Two 非靜態成員
two-3        // Two 構造器(主類靜態成員初始化)
main start   // main 方法
one-1        // 第二次 new Two
two-1
one-1        // 第三次 new Two
two-2

注意:one-3 只輸出一次,證明靜態成員僅在類首次主動使用時初始化一次。

「首次主動使用」觸發類初始化

不僅創建對象,以下操作也會觸發類初始化(執行靜態成員/塊):

  • 訪問靜態字段(非常量)
  • 調用靜態方法
  • 反射 Class.forName()
  • 初始化子類(會先初始化父類)

構造器鏈的限制

  • 一個構造器中只能調用一次 this() 或 super()
  • 調用語句必須是第一條語句
  • 若無顯式調用,編譯器自動插入 super()

實戰建議

  1. 父類務必提供無參構造器,或明確文檔要求子類調用哪個構造器
  2. 避免在構造器中調用可覆寫方法(子類成員尚未初始化)
  3. 靜態塊僅用於類級別的一次性初始化(如註冊驅動、加載配置)
  4. 實例塊適用於多構造器共享的初始化邏輯
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved