一、前言
Java 的密封類 (Sealed Classes) 是在 Java 15 (作為預覽功能) 引入,並在 Java 17 中正式成為標準功能的一項重要的語言特性。它的主要目的是為了限制類的繼承。 在沒有密封類之前,一個類可以被任何其他類繼承。密封類允許你明確地指定哪些類可以繼承它,從而提供更強大的控制權和封裝性。這對於建立可靠且可維護的類層次結構至關重要,尤其是在處理複雜的 API 設計時。 本文將從 Java 7 遷移至 Java 17 的角度,深入探討密封類的概念、使用方式、優點、以及相關的架構設計和範例。
目錄
二、密封類的基本概念
密封類的核心思想是
限制繼承
。一個密封類 (sealed class) 只能被預先定義好的類繼承。 這些允許繼承的類稱為
許可的子類 (permitted subclasses)
。 如果一個類被聲明為
sealed
,則必須使用
permits
關鍵字來聲明允許繼承它的類。
基本語法:
重要規則:
-
sealed
關鍵字: 用於聲明一個類為密封類。 -
permits
關鍵字: 用於指定允許繼承該密封類的類。 - 所有許可的子類必須與密封類在同一個模組中。
- 每個許可的子類必須直接或間接地繼承密封類。
-
每個許可的子類必須聲明其繼承方式:
final
(禁止繼承),sealed
(仍然是密封類), 或non-sealed
(開放繼承,回到傳統的繼承規則)。
三、密封類的優點
密封類提供了以下優點:
- 更好的封裝性: 密封類可以精確地控制哪些類可以繼承它,避免未預期的子類化。
- 更強的類型安全性: 編譯器可以利用密封類的知識進行更徹底的類型檢查,提高程式碼的安全性。
- 更好的可維護性: 通過明確的繼承關係,可以更容易地理解和修改類層次結構。
-
模式匹配的優化:
在
switch
表達式或instanceof
運算符中,可以對密封類的子類進行更精確的模式匹配,編譯器可以驗證所有可能的子類都被考慮到,減少default
分支的使用,提高程式碼的可靠性。
四、架構設計與工具
密封類主要影響了類層次結構的設計。 在設計 API 時,可以考慮使用密封類來限制外部程式碼對內部類的繼承,從而保證 API 的穩定性和安全性。
架構設計模式:
- 受保護的層次結構: 密封類可以用於建立受保護的類層次結構,允許內部類進行擴展,但限制外部類進行繼承。
- 代數數據類型 (Algebraic Data Types, ADT): 密封類可以與記錄 (Records) 和模式匹配 (Pattern Matching) 結合使用,模擬代數數據類型,提供更強大的數據建模能力。
工具支援:
- 編譯器: Java 編譯器會驗證密封類和許可的子類之間的關係,確保程式碼的正確性。
- IDE: 現代 IDE 通常提供對密封類的語法高亮、自動完成和重構支援。例如,可以快速找到密封類的許可子類,或者安全地重命名密封類。
五、範例
以下範例演示了密封類的用法:
執行結果:
在這個範例中,
Shape
是一個密封介面,它只允許
Circle
,
Rectangle
,
Square
這三個類實現它。
getArea
方法使用
if
表達式對不同的
Shape
子類進行處理,編譯器可以確保所有可能的
Shape
子類都被考慮到。
除了這三個類別之外,其他類別想要實作
Shape
,編譯時會報錯:

六、與Java 7至14的遷移考量
雖然密封類是在Java 15引入,正式版在17,但理解其對從較早Java版本遷移的影響仍然重要:
-
相容性: 在Java 17之前的版本中,密封類相關的語法(
sealed
,permits
,non-sealed
)會導致編譯錯誤。 為了在舊版本中保持相容性,需要避免使用這些關鍵字。 -
替代方案: 在 Java 7 至 14 中,可以使用抽象類和
final
類來模擬密封類的部分功能。例如,可以將一個類聲明為抽象類,並將所有允許的子類聲明為final
,從而防止其他類繼承。 -
逐步遷移: 如果需要將現有的程式碼遷移到 Java 17,可以逐步引入密封類。 首先,可以使用抽象類和
final
類來模擬密封類的功能,然後在升級到 Java 17 後,將其替換為真正的密封類。 -
**條件編譯:**可以使用條件編譯來根據 Java 版本選擇性地使用密封類:
執行結果:
七、總結
密封類是 Java 17 引入的一項強大的語言特性,它通過限制類的繼承來提高程式碼的封裝性、類型安全性和可維護性。 它可以與記錄和模式匹配結合使用,模擬代數數據類型,提供更強大的數據建模能力。 在設計 API 時,可以考慮使用密封類來建立受保護的類層次結構,從而保證 API 的穩定性和安全性。 從較早的 Java 版本遷移到 Java 17 時,需要考慮相容性問題,並可以使用抽象類和
final
類來模擬密封類的功能。 總之,密封類是一項值得學習和使用的特性,它可以幫助開發人員編寫更可靠、更安全、更易於維護的 Java 程式碼。
沒有留言:
張貼留言