具代表性的面試主題

Java 面試:Java 25 的 Flexible Constructor Bodies 改變了什麼?

程式題困難
Offer.cc 編輯團隊發佈 更新

題幹

請解釋 Java 25 Flexible Constructor Bodies 允許在 super() 或 this() 前執行什麼程式碼,並說明哪些存取仍然非法。

題幹與適用場景

Java 25 將 Flexible Constructor Bodies(JEP 513)定稿。面試官要求你說明建構子在明確 super(...)this(...) 前可以做什麼、為什麼不能讀取正在建構的實例,以及這對繼承與參數預處理有何影響。

面試官考察點

  • 是否理解建構子呼叫鏈與「實例尚未初始化」的安全約束。
  • 是否能區分允許的靜態邏輯、區域變數與對 this 的非法存取。
  • 是否能識別預覽版本、最終版本與編譯目標的遷移風險。

回答前需要釐清的問題

先確認目標是 JDK 25 的最終特性還是較早的 JEP 447/482/492 預覽,以及專案的 source、target 與執行時版本。也要確認問題關注語法、JVM 驗證,還是將舊的靜態參數轉換方法直接內嵌到建構子。

30 秒回答框架

傳統 Java 要求建構子的第一個敘述是 super(...)this(...)。Flexible Constructor Bodies 允許在明確建構子呼叫前執行受限的 prologue,例如計算區域變數或初始化目前類別尚未初始化的欄位;但不能讀取或呼叫正在建構的實例,也不能把未初始化的 this 傳給任意程式碼。這能直接預處理參數,同時維持父類建構早於可觀察實例狀態的安全規則。

分步驟深入解答

  1. 將建構子分成 prologue、明確建構子呼叫與剩餘 body;呼叫 this(...) 時仍沿著同一類別的建構鏈,呼叫 super(...) 時進入父類別。
  2. prologue 可宣告區域變數、執行不依賴實例狀態的表達式,並初始化目前類別的未初始化欄位;這些值可用於建構子參數。
  3. 禁止讀取實例欄位、呼叫實例方法、使用 this 作為參數,或讓任意可觀察程式碼接觸半初始化物件。
  4. JVM 與編譯器必須追蹤哪些欄位仍未初始化,確保父類建構子看不到違反初始化順序的狀態;靜態方法與常數可在規則允許時使用。
  5. 遷移時刪除僅為準備 super(...) 參數而存在的靜態 helper,但保留有副作用、可重用或需要獨立測試的邏輯邊界。
  6. 使用 JDK 25 編譯器與目標執行時驗證;若專案仍以舊 source/target 編譯,新的語法不能直接提交。
java
class Child extends Parent {
    private final String normalized;

    Child(String raw) {
        var value = raw.trim();       // prologue: local computation
        super(value);                 // explicit constructor invocation
        this.normalized = value;
    }
}

高品質示範回答

JEP 513 允許建構子在 super(...)this(...) 前有受限的 prologue。它適合做不依賴實例狀態的參數預處理與目前類別欄位初始化,但仍禁止讀取實例欄位、呼叫實例方法或把半初始化的 this 傳出去。編譯器與 JVM 需確保父類建構子只看到合法的初始化狀態。回答時我會區分 JEP 447/482/492 預覽與 JDK 25 定稿,並檢查 source、target、執行時版本。它減少為一小段參數轉換而建立靜態 helper 的需要,卻沒有取消建構順序與繼承安全約束。

常見錯誤

  • 說成「任何敘述都能放在 super() 前」。
  • 忽略 this 尚未完成初始化,允許呼叫實例方法或讀取欄位。
  • 把預覽版 JEP 編號當成 JDK 25 的最終編號。
  • 只改原始碼,不檢查編譯目標與部署執行時。
  • 為了示例方便在 prologue 引入外部可觀察副作用。

追問及應對

為什麼允許區域計算卻禁止讀取 this

區域計算不會觀察半初始化物件;讀取欄位或呼叫方法可能觸發動態分派、洩露不完整狀態或讓父類邏輯看到錯誤不變量。

this(...)super(...) 前的規則一樣嗎?

兩者都受早期建構情境約束;this(...) 會繼續目前類別的建構鏈,super(...) 會進入父類,因此都不能讓實例狀態在合法初始化前被觀察。

什麼時候不該內嵌原來的 helper?

如果 helper 有多個呼叫點、複雜副作用、獨立測試價值或清晰的模組邊界,保留 helper 更易維護;這項特性只是語法能力,不是重構要求。

如何相容舊 JDK?

維持舊 source/target 時不能使用新語法;可暫時保留原有參數準備方式,待編譯器、執行時與發布矩陣都升級後再遷移。

公開來源

同類題目

相關面試工具

用 Screenshot 處理演算法題

截圖題目後,依序看約束、解法、程式碼、邊界條件和複雜度。

查看工具