Java17新特性-Java类(接口)的新类型——密封类-《Java笔记》

admin 2025-10-19 02:49:03 编程 来源:ZONE.CI 全球网 0 阅读模式

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

密封类

在以往的Java类继承中,Java类的继承控制非常有限,仅能通过final关键字和访问控制符来控制类的继承。例如final类无法被集成;包私有类仅仅只能在该包下进行继承。这显然是不够的。如果一个功能只允许出现在Phone和Pad上,不允许出现在Computer上。如果不对该功能的继承实现进行限制,开发人员将很容易滥用该功能的实现类,错误地重用一些代码。这就是密封类产生的原因。

密封类的声明

:::tips 密封类不仅仅可以是类,也可以是接口。文章中的密封类为统称 ::: 密封类(接口)可以明确哪些类和接口可以对其扩展或实现。可以通过sealed修饰符来表明某个类是密封类。但是下面是一个错误的密封类声明:

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

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

  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. }
  16. }

密封类子类的类型

在上面示例中,密封类(接口)的实现类用了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. public final class SonService extends SealedServiceImpl {
  11. }

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

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

总结一下,密封类的子类要么是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 {
  14. }

使用SonService间接实现了SealedService,结果报错,报错信息要求必须是直接的继承关系。Java类(接口)的新类型——密封类 - 图1错误的密封类继承实现从上图可以看出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();
  7. }

总结

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

以太坊cppgolang区别 编程

以太坊cppgolang区别

以太坊是一种去中心化的开源平台,它采用智能合约技术,旨在构建和运行不受干扰的分布式应用程序。作为目前最受欢迎的区块链平台之一,以太坊提供了多种编程语言的支持,其
progolang 编程

progolang

Go语言(Golang)是由Google开发的一门静态类型编程语言。作为一名专业的Golang开发者,我深知这门语言的优势和特点。在本文中,我将介绍Golang
golangn个发送者 编程

golangn个发送者

Golang是一种开源的编程语言,由Google团队开发,旨在提高程序的并发性和简化软件开发过程。在Go语言中,有时需要向多个接收者发送信息。本文将介绍如何在G
golang技能图谱 编程

golang技能图谱

从互联网行业的快速发展到人工智能技术的日益成熟,各种编程语言也应运而生。而在这众多的编程语言中,Golang(即Go)作为一门强大且高效的开发语言备受关注。Go
评论:0   参与:  0