Java類(接口)的新類型——密封類
點擊關(guān)注公眾號,Java干貨及時送達(dá)
密封類是Java 17正式支持的一個新特性,它讓Java中類的繼承可以更加細(xì)粒度的進(jìn)行控制。今天就來認(rèn)識一下這個新的功能。
密封類
在以往的Java類繼承中,Java類的繼承控制非常有限,僅能通過final關(guān)鍵字和訪問控制符來控制類的繼承。例如final類無法被集成;包私有類僅僅只能在該包下進(jìn)行繼承。
這顯然是不夠的。如果一個功能只允許出現(xiàn)在Phone和Pad上,不允許出現(xiàn)在Computer上。如果不對該功能的繼承實現(xiàn)進(jìn)行限制,開發(fā)人員將很容易濫用該功能的實現(xiàn)類,錯誤地重用一些代碼。這就是密封類產(chǎn)生的原因。
密封類的聲明
?密封類不僅僅可以是類,也可以是接口。文章中的密封類為統(tǒng)稱
密封類(接口)可以明確哪些類和接口可以對其擴展或?qū)崿F(xiàn)。你可以通過sealed修飾符來表明某個類是密封類。但是下面是一個錯誤的密封類聲明:
/**
?*?這是一個錯誤的示范
?*/
public?sealed?interface?SealedService?{
???
????void?doSomething();
}
密封類(接口)在聲明的時候必須明確可繼承(實現(xiàn))的范圍,所以上面的寫法是錯誤的。必須用permits子句指定允許擴展密封類的類,而且permits關(guān)鍵字位于extends或者implements之后。
?簡而言之,密封類明確了哪些其他類(或接口)可以擴展它們。
下面是正確的寫法:
/**
?*?這是一個正確的示范,明確了可繼承的子類為{@link?SealedServiceImpl}
?*?該密封類接口同時實現(xiàn)了{(lán)@link?SuperService}
?*/
public?sealed?interface?SealedService?extends?SuperService?permits?SealedServiceImpl?{
????void?doSomething();
}
/**
?*?密封類子類
?*/
public?final?class?SealedServiceImpl?implements?SealedService?{
????@Override
????public?void?doSomething()?{
????????System.out.println("這是一個密封類子類");
????}
}
密封類子類的類型
在上面示例中,密封類(接口)的實現(xiàn)類用了final關(guān)鍵字標(biāo)記,當(dāng)然密封類的實現(xiàn)類還可以是密封類:
/**
?*?密封類子類
?*/
public?sealed?class?SealedServiceImpl?implements?SealedService?permits?SonService?{
????@Override
????public?void?doSomething()?{
????????System.out.println("這是一個密封類子類");
????}
}
public?final?class?SonService?extends?SealedServiceImpl?{
}
那么難道密封類(接口)的子類只能是final類或者密封類,就不能再擴展了?答案是否定的,只需要使用關(guān)鍵字non-sealed顯式聲明密封類的繼承實現(xiàn)為非密封類就可以繼續(xù)擴展了。
public?non-sealed?class?SealedServiceImpl?implements?SealedService?{
????@Override
????public?void?doSomething()?{
????}
????/**
?????*?用{@code?non-sealed}聲明非密封類,就可以繼續(xù)擴展了
?????*/
????static?class?NonSealedExtend?extends?SealedServiceImpl?{
????}
}
總結(jié)一下,密封類的子類要么是final Class;要么是sealed Class;要么是non-sealed Class。
permits 聲明的類必須是直接子類
密封類permits關(guān)鍵字聲明的子類必須是直接實現(xiàn)類,為了證明這一點我們這樣寫:
/**
?*?錯誤的示范
?*/
public?sealed?interface?SealedService?extends?SuperService?permits?SealedServiceImpl,?SonService?{
????void?doSomething();
}
public?sealed?class?SealedServiceImpl?implements?SealedService?permits?SonService?{
????@Override
????public?void?doSomething()?{
????????System.out.println("這是一個密封類子類");
????}
}
public?final?class?SonService?extends?SealedServiceImpl?{
}
我使用SonService間接實現(xiàn)了SealedService,結(jié)果報錯,報錯信息要求必須是直接的繼承關(guān)系。

從上圖可以看出SonService并非直接實現(xiàn)SealedService,這樣會打破密封類的規(guī)則,所以無法編譯通過。
?密封類中
permits關(guān)鍵字聲明的子類必須是直接子類,不可間接實現(xiàn)。
密封類不支持匿名類和函數(shù)式接口
由于密封類必須明確繼承實現(xiàn)關(guān)系,所以它不支持匿名類。
/**
?*?密封類無法使用匿名類
?*
?*?@return?the?sealed?service
?*/
public?SealedService?sealedService(){
????//?提示?Anonymous?classes?must?not?extend?sealed?classes
????return?new?SealedService()?{
????????@Override
????????public?void?doSomething()?{
????????????
????????}
????};
}
同樣也不支持函數(shù)式接口:
/**
?*?錯誤的示范
?*/
@FunctionalInterface
public?sealed?interface?SealedService?permits?SealedServiceImpl?{
????void?doSomething();
}
總結(jié)
密封類已經(jīng)在Java 17中正式轉(zhuǎn)正,這也是Java 17的非常重要的特性之一。對于需要細(xì)粒度控制繼承關(guān)系的場景來說是非常有用的。
往 期 推 薦
1、致歉!抖音Semi Design承認(rèn)參考阿里Ant Design
2、對比7種分布式事務(wù)方案,還是偏愛阿里開源的Seata,真香!
點分享
點收藏
點點贊
點在看





