2025年2月9日 星期日

Java 7 to 17 SealedClasses

一、前言

一、前言

返回目錄

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 sealed class error

六、與Java 7至14的遷移考量

返回目錄

雖然密封類是在Java 15引入,正式版在17,但理解其對從較早Java版本遷移的影響仍然重要:

  1. 相容性: 在Java 17之前的版本中,密封類相關的語法( sealed , permits , non-sealed )會導致編譯錯誤。 為了在舊版本中保持相容性,需要避免使用這些關鍵字。

  2. 替代方案: 在 Java 7 至 14 中,可以使用抽象類和 final 類來模擬密封類的部分功能。例如,可以將一個類聲明為抽象類,並將所有允許的子類聲明為 final ,從而防止其他類繼承。

  3. 逐步遷移: 如果需要將現有的程式碼遷移到 Java 17,可以逐步引入密封類。 首先,可以使用抽象類和 final 類來模擬密封類的功能,然後在升級到 Java 17 後,將其替換為真正的密封類。

  4. **條件編譯:**可以使用條件編譯來根據 Java 版本選擇性地使用密封類:

    執行結果:

七、總結

返回目錄

密封類是 Java 17 引入的一項強大的語言特性,它通過限制類的繼承來提高程式碼的封裝性、類型安全性和可維護性。 它可以與記錄和模式匹配結合使用,模擬代數數據類型,提供更強大的數據建模能力。 在設計 API 時,可以考慮使用密封類來建立受保護的類層次結構,從而保證 API 的穩定性和安全性。 從較早的 Java 版本遷移到 Java 17 時,需要考慮相容性問題,並可以使用抽象類和 final 類來模擬密封類的功能。 總之,密封類是一項值得學習和使用的特性,它可以幫助開發人員編寫更可靠、更安全、更易於維護的 Java 程式碼。

沒有留言:

張貼留言