当前位置: 首页 > 科技观察

一种新型的Java类(接口)——密封类

时间:2023-03-18 14:04:05 科技观察

密封类是Java17正式支持的新特性,它可以让Java中的类继承更加细粒度。今天就来体验这个新功能吧。密封类在以前的Java类继承中,Java类的继承控制非常有限,只能通过final关键字和访问控制符号来控制类的继承。比如final类不能集成;package-private类只能在该包下被继承。这显然是不够的。如果一个功能只允许出现在Phone和Pad上,则不允许出现在Computer上。如果对该函数的继承实现没有限制,开发者很容易滥用该函数的实现类,错误地复用部分代码。这就是创建密封类的原因。密封类的声明密封类不仅可以是类,也可以是接口。文章中的密封类统称为密封类(接口),可以明确哪些类和接口可以被扩展或实现。您可以使用sealed修饰符来指示类是密封类。但是下面是一个错误的密封类声明:/***这是一个错误的演示*/publicsealedinterfaceSealedService{voiddoSomething();}密封类(接口)在声明的时候必须明确定义继承(实现)的范围,所以上面的拼写错误。必须使用permits子句指定允许扩展密封类的类,permits关键字位于extends或implements之后。简而言之,密封类明确了哪些其他类(或接口)可以扩展它们。以下是正确的写法:/***这是正确的示范,可继承的子类指定为{@linkSealedServiceImpl}*密封类接口也实现了{@linkSuperService}*/publicsealedinterfaceSealedServiceextendsSuperServicepermitsSealedServiceImpl{voiddoSomething();}/***密封类子类*/publicfinalclassSealedServiceImplimplementsSealedService{@OverridepublicvoiddoSomething(){System.out.println("这是一个密封类子类");}}密封类子类的类型在上面的例子中,密封类(接口的实现类)是用final关键字标记的。当然密封类的实现类也可以是密封类:}publicfinalclassSonServiceextendsSealedServiceImpl{}那么有没有可能密封类(接口)的子类只能是final类或者密封类,不能扩展呢?答案是否定的,只要用关键字non-sealed显式声明继承sealed类作为非sealed类实现,就可以继续扩展了。publicnon-sealedclassSealedServiceImplimplementsSealedService{@OverridepublicvoiddoSomething(){}/***使用{@codenon-sealed}声明一个非密封类,可以继续扩展*/staticclassNonSealedExtendsSealedServiceImpl{}}总结一下,一个子类密封类是最终类;密封类;或非密封类。permits声明的类必须是直接子类。permits关键字声明的子类必须是直接实现类。为了证明这一点,我们这样写:{}我用SonService间接实现了SealedService,结果报错。错误信息必须是直接的继承关系。错误的密封类继承实现从上图可以看出,SonService并没有直接实现SealedService,这样会破坏密封类的规则,所以无法通过编译。sealed类中permit关键字声明的子类必须是直接子类,不能间接实现。密封类不支持匿名类和函数式接口由于密封类必须显式继承实现关系,所以不支持匿名类。/***密封类不能使用匿名类**@returnthesealedservice*/publicSealedServicesealedService(){//提示AnonymousclassesmustnotextendsealedclassesreturnnewSealedService(){@OverridepublicvoiddoSomething(){}};}也不支持函数式接口:/***错误演示*/@FunctionalInterfacepublicsealedinterfaceSealedServicepermitsSealedServiceImpl{voiddoSomething();}总结密封类在Java17中正式成为正则,这也是Java17非常重要的特性之一,对于需要细粒度控制继承关系的场景非常有用.