Java类(接口)的新类型-密封类

开发 后端
在以往的Java类继承中,Java类的继承控制非常有限,仅能通过final关键字和访问控制符来控制类的继承。例如final类无法被集成;包私有类仅仅只能在该包下进行继承。

[[432662]]

密封类是Java 17正式支持的一个新特性,它让Java中类的继承可以更加细粒度的进行控制。今天就来认识一下这个新的功能。

密封类

在以往的Java类继承中,Java类的继承控制非常有限,仅能通过final关键字和访问控制符来控制类的继承。例如final类无法被集成;包私有类仅仅只能在该包下进行继承。

这显然是不够的。如果一个功能只允许出现在Phone和Pad上,不允许出现在Computer上。如果不对该功能的继承实现进行限制,开发人员将很容易滥用该功能的实现类,错误地重用一些代码。这就是密封类产生的原因。

密封类的声明

密封类不仅仅可以是类,也可以是接口。文章中的密封类为统称

密封类(接口)可以明确哪些类和接口可以对其扩展或实现。你可以通过sealed修饰符来表明某个类是密封类。但是下面是一个错误的密封类声明:

  1. /** 
  2.  * 这是一个错误的示范 
  3.  */ 
  4. public sealed interface SealedService { 
  5.     
  6.     void doSomething(); 

密封类(接口)在声明的时候必须明确可继承(实现)的范围,所以上面的写法是错误的。必须用permits子句指定允许扩展密封类的类,而且permits关键字位于extends或者implements之后。

简而言之,密封类明确了哪些其他类(或接口)可以扩展它们。

下面是正确的写法:

  1. /** 
  2.  * 这是一个正确的示范,明确了可继承的子类为{@link SealedServiceImpl} 
  3.  * 该密封类接口同时实现了{@link SuperService} 
  4.  */ 
  5. public sealed interface SealedService extends SuperService permits SealedServiceImpl { 
  6.     void doSomething(); 
  7.  
  8. /** 
  9.  * 密封类子类 
  10.  */ 
  11. public final class SealedServiceImpl implements SealedService { 
  12.     @Override 
  13.     public void doSomething() { 
  14.         System.out.println("这是一个密封类子类"); 
  15.     } 

密封类子类的类型

在上面示例中,密封类(接口)的实现类用了final关键字标记,当然密封类的实现类还可以是密封类:

  1. /** 
  2.  * 密封类子类 
  3.  */ 
  4. public sealed class SealedServiceImpl implements SealedService permits SonService { 
  5.     @Override 
  6.     public void doSomething() { 
  7.         System.out.println("这是一个密封类子类"); 
  8.     } 
  9.  
  10.  
  11. public final class SonService extends SealedServiceImpl { 

那么难道密封类(接口)的子类只能是final类或者密封类,就不能再扩展了?答案是否定的,只需要使用关键字non-sealed显式声明密封类的继承实现为非密封类就可以继续扩展了。

  1. public non-sealed class SealedServiceImpl implements SealedService { 
  2.     @Override 
  3.     public void doSomething() { 
  4.  
  5.     } 
  6.  
  7.     /** 
  8.      * 用{@code non-sealed}声明非密封类,就可以继续扩展了 
  9.      */ 
  10.     static class NonSealedExtend extends SealedServiceImpl { 
  11.  
  12.     } 
  13.  

总结一下,密封类的子类要么是final Class;要么是sealed Class;要么是non-sealed Class。

permits 声明的类必须是直接子类

密封类permits关键字声明的子类必须是直接实现类,为了证明这一点我们这样写:

  1. /** 
  2.  * 错误的示范 
  3.  */ 
  4. public sealed interface SealedService extends SuperService permits SealedServiceImpl, SonService { 
  5.     void doSomething(); 
  6.  
  7. public sealed class SealedServiceImpl implements SealedService permits SonService { 
  8.     @Override 
  9.     public void doSomething() { 
  10.         System.out.println("这是一个密封类子类"); 
  11.     } 
  12.  
  13. public final class SonService extends SealedServiceImpl { 

我使用SonService间接实现了SealedService,结果报错,报错信息要求必须是直接的继承关系。

错误的密封类继承实现

从上图可以看出SonService并非直接实现SealedService,这样会打破密封类的规则,所以无法编译通过。

密封类中permits关键字声明的子类必须是直接子类,不可间接实现。

密封类不支持匿名类和函数式接口

由于密封类必须明确继承实现关系,所以它不支持匿名类。

  1. /** 
  2.  * 密封类无法使用匿名类 
  3.  * 
  4.  * @return the sealed service 
  5.  */ 
  6. public SealedService sealedService(){ 
  7.     // 提示 Anonymous classes must not extend sealed classes 
  8.     return new SealedService() { 
  9.         @Override 
  10.         public void doSomething() { 
  11.              
  12.         } 
  13.     }; 

同样也不支持函数式接口:

  1. /** 
  2.  * 错误的示范 
  3.  */ 
  4. @FunctionalInterface 
  5. public sealed interface SealedService permits SealedServiceImpl { 
  6.     void doSomething(); 

总结

 

密封类已经在Java 17中正式转正,这也是Java 17的非常重要的特性之一。对于需要细粒度控制继承关系的场景来说是非常有用的。

 

责任编辑:武晓燕 来源: 码农小胖哥
相关推荐

2022-03-29 07:20:04

密封类.NET性能

2012-02-29 09:32:01

Java

2020-06-29 07:52:17

Java工具类开发

2011-07-10 14:07:59

JAVA

2011-07-12 15:58:48

java抽象类接口

2009-04-30 15:15:01

Java抽象类接口

2013-12-10 16:44:30

2020-06-27 09:01:53

Java包装类编程语言

2010-03-04 09:40:04

Java接口抽象类

2011-03-07 13:59:00

2011-05-19 18:01:56

JAVA

2022-11-15 09:57:51

Java接口

2009-06-12 13:48:13

数据类型string类Java教程

2009-06-16 11:30:00

Java抽象类Java接口

2009-06-14 21:31:29

Java抽象类Java接口

2011-12-22 10:48:21

Java

2015-03-23 09:33:43

Java抽象类Java接口Java

2021-04-08 10:10:46

JavaSimpleDateFList接口

2020-07-08 07:56:08

Java工具类包装类

2009-07-22 09:31:59

Scala类类层级Java类
点赞
收藏

51CTO技术栈公众号