首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java 構造器調用重寫方法的陷阱:字段初始化順序導致的「詭異」輸出

     編輯:程式設計綜合問答

代碼與輸出

public class A {
    public A() { init(); }
    protected void init() {}
    static class B extends A {
        int i, j = 999;
        protected void init() {
            System.out.println("i=" + i + ", j=" + j); // 輸出 0, 0
            i = 888; j = 111;
        }
    }
    public static void main(String[] args) {
        B b = new B();
        System.out.println("i=" + b.i + ", j=" + b.j); // 輸出 888, 999
    }
}

執行流程解析

  1. new B() → 隱式調用 super() → 執行 A() 構造器。
  2. A() 調用 init(),因多態調用 B.init()。
  3. 此時 B 的字段 i 默認值 0,j 顯式初始化 999 尚未執行(字段初始化在構造器體之前,但父類構造器先於子類字段初始化運行)。
  4. B.init() 打印 0, 0(注意:j 的顯式賦值 999 尚未執行,因子類字段初始化在父類構造器完成後、子類構造器體之前)。
  5. 父類構造器結束,執行子類字段初始化:j = 999(覆蓋了 init() 中的 111),i 無顯式初始化保持 888。
  6. 子類構造器體無代碼,最終 b.i=888, b.j=999。

核心教訓

構造器中不要調用可被重寫的方法(即非 private、final、static 方法)。此時子類尚未完全初始化,字段可能處於默認值狀態,導致邏輯錯誤。

最佳實踐

  • 將初始化邏輯放入 private 方法或構造器體直接編寫。
  • 若需多態初始化,採用工廠模式或兩階段初始化(構造後調用 init())。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved