Java 的 final 關鍵字可修飾類別、方法與變數(含成員變數與區域變數)。雖然 C++ 程式設計師常將其類比為 const 或 #define,但兩者在語義上存在顯著差異。
經典範例是 String 類別。被 final 修飾的類別無法被繼承,其所有成員方法會隱式指定為 final,但成員變數不受影響。除非有明確需求(如確保語義不被修改),一般不建議將類別設計為 final。若 String 可被繼承,將能定義可修改的字串類別,這對使用者幾乎是災難性的。
final 方法內聯調用,但現代 JVM 已透過 JIT 編譯器自動優化,不再需依賴 final 達此效果。private 方法隱式為 final,因其不可被重新定義。僅在明確禁止覆寫時才應使用 final 修飾方法。
編譯器對 final 變數(基本型別與 String)進行編譯期常量優化。若在編譯期可確定值,會視為編譯期常量。此優化通常不影響邏輯,但使用 == 比較時可能產生預期外結果。
良好習慣:除非變數必須可變,否則盡量宣告為 final。方法參數若無需修改,加上 final 可防止無意變更,尤其在冗長複雜的方法中更為重要。
執行緒安全:final 能確保初始化安全性,不可變物件在多執行緒共享時無需同步。將多個需保持一致的基本型別變數封裝於類別中並以 final 修飾,變數修改轉為賦值操作(原子操作),可避免鎖同步開銷,雖會產生較多小物件增加 GC 壓力,但通常可接受。
匿名內部類限制:匿名內部類只能存取 final 區域變數,根本原因在於區域變數生命週期(方法結束即銷毀)與匿名內部類物件生命週期不一致。final 實際上將區域變數「複製」一份作為內部類的資料成員,解決生命週期不匹配問題。