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

Java 繼承初始化順序深度解析:從靜態塊到構造器的完整調用鏈

     編輯:Java 程式設計入門

繼承是 Java 核心特性,但初始化順序往往讓開發者困惑,尤其是涉及靜態成員、實例塊、構造器、向上轉型時。本文通過完整案例,系統梳理執行流程。

父類與子類定義


// 父類
public class TestStatic {
    public static String name = "china";

    { System.out.println("========父類實例塊========"); }

    static {
        name = "England";
        System.out.println("========父類靜態塊======");
    }

    TestStatic() {
        System.out.println("========父類構造器========");
    }

    public static void main(String[] args) {
        System.out.println("========父類main========" + name);
    }

    public void test() {
        System.out.println("========父類test========");
    }
}

// 子類
public class TestExtendStatic extends TestStatic {
    // public static String name = "HUBEI";

    { System.out.println("========子類實例塊========"); }

    static {
        // name = "SUIZHOU";
        System.out.println("========子類靜態塊======");
    }

    TestExtendStatic() {
        System.out.println("========子類構造器========");
    }

    @Override
    public void test() {
        System.out.println("========子類test========");
    }

    public static void main(String[] args) {
        System.out.println("========子類main========" + name);
        TestStatic ts = new TestExtendStatic(); // 向上轉型
        ts.test();
    }
}

執行輸出與順序解析


========父類靜態塊======      ← 1. 父類靜態字段/靜態塊(按定義順序)
========子類靜態塊======      ← 2. 子類靜態字段/靜態塊
========子類main========England ← 3. 子類 main 執行,打印繼承的 name="England"
========父類實例塊========    ← 4. new 子類:父類實例字段/實例塊
========父類構造器========    ← 5. 父類構造器
========子類實例塊========    ← 6. 子類實例字段/實例塊
========子類構造器========    ← 7. 子類構造器
========子類test============  ← 8. 多態調用:實際執行子類重寫的 test()

核心規律總結

  1. 靜態優先:類加載階段,父類→子類,靜態字段與靜態塊按「定義順序」交織執行
  2. 實例跟隨 new:new Child() 觸發:父類實例字段/塊 → 父類構造器 → 子類實例字段/塊 → 子類構造器
  3. 構造器鏈:子類構造器隱式調用 super(),形成遞歸鏈,父類構造器最先完成
  4. 多態方法調用:構造器鏈完成後,對象已完全初始化,調用重寫方法走動態分派

關鍵驗證場景

場景 A:多次 new 子類

靜態塊只執行一次(類加載時),實例塊與構造器每次 new 都執行。

場景 B:new 父類實例


TestStatic ts = new TestStatic();  // 不加載子類靜態塊!
ts.test();

輸出:父類靜態塊 → 父類實例塊 → 父類構造器 → 父類 test()。
若在父類 main 中執行,子類靜態塊不會加載。

場景 C:main 方法執行時機

  • 類加載 → 靜態塊 → main 方法 → new 對象 → 實例塊/構造器
  • 非靜態塊/構造器永遠在 main 之後(因為 main 中才 new)

向上轉型本質


TestStatic ts = new TestExtendStatic();  // 引用類型是父類,對象類型是子類
TestExtendStatic ts2 = new TestExtendStatic(); // 引用類型是子類

兩種寫法觸發的初始化鏈完全一致。區別僅在編譯期可見成員與運行期多態調用。

總結口訣

先靜後動,先父後子,按序定義,構造收尾。多態調用,對象完全初始化後方生效。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved