詳解 Java 17 中新推出的密封類

来源:https://www.cnblogs.com/didispace/archive/2022/05/06/16228524.html
-Advertisement-
Play Games

Java 17推出的新特性Sealed Classes經歷了2個Preview版本(JDK 15中的JEP 360、JDK 16中的JEP 397),最終定稿於JDK 17中的JEP 409。Sealed Classes有兩種主流翻譯:密封類、封閉類。個人喜歡前者多一些,所以在本文中都稱為密封類。其 ...


Java 17推出的新特性Sealed Classes經歷了2個Preview版本(JDK 15中的JEP 360、JDK 16中的JEP 397),最終定稿於JDK 17中的JEP 409。Sealed Classes有兩種主流翻譯:密封類、封閉類。個人喜歡前者多一些,所以在本文中都稱為密封類。其實Sealed Classes的其他許多語言中並不是什麼新鮮事物,C#、Scala等高級語言中都有類似的名稱,但意義和作用各不相同。下麵就來一起認識一下Java 17中的Sealed Classes。

密封類的作用

在面向對象語言中,我們可以通過繼承(extend)來實現類的能力復用、擴展與增強。但有的時候,有些能力我們不希望被繼承了去做一些不可預知的擴展。所以,我們需要對繼承關係有一些限制的控制手段。而密封類的作用就是限制類的繼承

已有的限制手段

對於繼承能力的控制,Java很早就已經有一些了,主要是這兩種方式:

  1. final修飾類,這樣類就無法被繼承了
  2. package-private類(非public類),可以控制只能被同一個包下的類繼承

但很顯然,這兩種限制方式的粒度都非常粗,如果有更精細化的限制需求的話,是很難實現的。

新特性:密封類

為了進一步增強限制能力,Java 17中的密封類增加了幾個重要關鍵詞:

  • sealed:修飾類/介面,用來描述這個類/介面為密封類/介面
  • non-sealed:修飾類/介面,用來描述這個類/介面為非密封類/介面
  • permits:用在extendsimplements之後,指定可以繼承或實現的類

下麵我們通過一個例子來理解這幾個關鍵詞的用法,更多Java新特性,歡迎關註Java前沿專欄,文檔形式看Java新特性,閱讀學習體驗更佳,持續更新,收藏保存!

假設我們要設計一個游戲,這個游戲給用戶選擇的英雄種類分為三大類:

  • 坦克
  • 輸出
  • 輔助

每個種類下又有各種不同的具體英雄。所以,從我們傳統的面向設計思路,會這樣來創建:

// 英雄基類
public class Hero {

}

// 坦克英雄的抽象
public class TankHero extends Hero {

}

// 輸出英雄的抽象
public class AttackHero extends Hero {

}

// 輔助英雄的抽象
public class SupportHero extends Hero {

}

// 坦克英雄:阿利斯塔
public class Alistar extends TankHero {

}

// 輸出英雄:伊澤瑞爾
public class Ezreal extends AttackHero {

}

// 輔助英雄:索拉卡
public class Soraka extends SupportHero {

}

整體結構有三層,具體如下圖所示:

  • 第一層:Hero是所有英雄的基類,定義英雄的基礎屬性
  • 第二層:按英雄的分類的三個不同抽象,定義同類英雄的公共屬性
  • 第三層:具體英雄的定義

這個時候,為了避免開發人員在創建新英雄的時候,搞亂這樣的三層結構。就可以通過引入密封類的特性來做限制。

假設我們希望第一、第二層是穩定的,對於第二層英雄種類的抽象不允許再增加,此時我們就可以這樣寫:

public sealed class Hero permits TankHero, AttackHero, SupportHero {

}

通過sealed關鍵詞和permitspermits關鍵來定義Hero是一個需要密封的類,並且它的子類只允許為TankHero, AttackHero, SupportHero這三個。

完成這個改造之後,我們會發現TankHero, AttackHero, SupportHero這三個類開始報錯了,具體錯誤如下:

sealed, non-sealed or final modifiers expected

這是因為父類Hero被sealed修飾之後,sealed的密封要求被傳遞過來,此時子類就必須在sealednon-sealedfinal之間選擇一個定義,它們分別代表:

  • sealed:繼續延續密封類特性,可以繼續指定繼承的類,並傳遞密封定義給子類
  • non-sealed:聲明這個類為非密封類,可以被任意繼承
  • final:不允許繼承

根據上面的假設需求,第一、第二層穩定,允許第三層具體英雄角色可以後期不斷增加新英雄,所以三類抽象英雄的定義可以這樣編寫:

public non-sealed class TankHero extends Hero {

}

而對於第三層的英雄角色,已經是最後的具體實現,則可以使用final定義來阻斷後續的繼承關係,比如這樣:

public final class Ezreal extends AttackHero {

}

通過這樣的設置,這三層英雄的結構中第一第二層就得到了比較好的保護。

好了,今天的分享就到這裡!如果您學習過程中如遇困難?可以加入我們超高質量的技術交流群,參與交流與討論,更好的學習與進步!另外,不要走開,關註我!持續更新Java新特性專欄,文檔形式看Java新特性,閱讀學習體驗更佳!

歡迎關註我的公眾號:程式猿DD。第一時間瞭解前沿行業消息、分享深度技術乾貨、獲取優質學習資源


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 在學習python的過程中,很多人會說,需要我的英語基礎特別好嘛? 是不需要的,它所常用的單詞其實就那麼多,只要你用心和常去敲敲代碼,其實是非常容易的。 下麵我整理了一些python常用單詞,你可以看一看,希望對你帶來幫助~ 由於不太好打出來,我就用圖片來代替啦~ 好啦~就到這裡啦~辭彙還是很 ...
  • ReentrantLock ReentrantLock功能 ReentrantLock和synchronized一樣是可重入的 可重入即當線程擁有了鎖時,當該線程再次請求鎖資源的時候,線程是可以再次成功獲得的。 static ReentrantLock lock = new ReentrantLoc ...
  • Spring Ioc源碼分析系列--Ioc的基礎知識準備 本系列文章代碼基於Spring Framework 5.2.x Ioc的概念 在Spring里,Ioc的定義為The IoC Container,翻譯過來也就是Ioc容器。為什麼會被叫做容器呢?我們來比對一下日常生活中的容器,也就是那些瓶瓶罐 ...
  • 上一篇文章https://www.cnblogs.com/redwinter/p/16198942.html介紹了Spring的註解的解析過程以及Spring Boot自動裝配的原理,大概回顧下:Spring 解析註解是通過BeanFactoryPostProcessor的子介面BeanDefini ...
  • 大家好,我是二哥! 很早之前,就有小伙伴給我反饋說《Java 程式員進階之路》經常有圖片不顯示或者載入緩慢。 但由於白嫖(GitHub圖床+jsdelivr CDN)的力量實在是太過強大了(狗頭),再加上我本人沒有遇到過這個問題,所以就一直拖延著,遲遲沒有行動。 直到某一天,我神秘的流量用光了,上不 ...
  • 一個工作七年的小伙伴,竟然不知道”wait”和“notify”為什麼要在Synchronized代碼塊裡面。 好吧,如果屏幕前的你也不知道,請在評論區打上”不知道“。 對於這個問題,我們來看看普通人和高手的回答。 普通人: 額。。。。。。。。。。。。 高手: wait和notify用來實現多線程之間 ...
  • 前言 昨天在跟小伙伴聊天,當他談起自己正在做的項目時,一臉愁容。 他吐槽道:“該項目的 Python 代碼庫由多個人共同維護。由於每個人使用的編輯器不同,每個人的編碼風格也不同,最終導致了 代碼的縮進千奇百怪:有縮進 2 個空格的,有縮進 4 個空格的,有縮進 8 個空格,有縮進一個 Tab 的,更 ...
  • 來源:cnblogs.com/juncaoit/p/12422752.html 一直以為這個方法是java8的,今天才知道是是1.7的時候,然後翻了一下源碼。 這篇文章中會總結一下與a.equals(b)的區別,然後對源碼做一個小分析。 值是null的情況 1、a.equals(b), a 是nul ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...