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。第一时间了解前沿行业消息、分享深度技术干货、获取优质学习资源

详解 Java 17 中新推出的密封类的更多相关文章

  1. 详解Java 8中Stream类型的“懒”加载

    在进入正题之前,我们需要先引入Java 8中Stream类型的两个很重要的操作: 中间和终结操作(Intermediate and Terminal Operation) Stream类型有两种类型的 ...

  2. 详解Java中的clone方法

    详解Java中的clone方法 参考:http://blog.csdn.net/zhangjg_blog/article/details/18369201/ 所谓的复制对象,首先要分配一个和源对象同样 ...

  3. 【转帖】windows命令行中java和javac、javap使用详解(java编译命令)

    windows命令行中java和javac.javap使用详解(java编译命令) 更新时间:2014年03月23日 11:53:15   作者:    我要评论 http://www.jb51.ne ...

  4. 超全详解Java开发环境搭建

    摘自:https://www.cnblogs.com/wangjiming/p/11278577.html 超全详解Java开发环境搭建   在项目产品开发中,开发环境搭建是软件开发的首要阶段,也是必 ...

  5. 详解Java GC的工作原理+Minor GC、FullGC

    详解Java GC的工作原理+Minor GC.FullGC 引用地址:http://www.blogjava.net/ldwblog/archive/2013/07/24/401919.html J ...

  6. Protocol Buffer技术详解(Java实例)

    Protocol Buffer技术详解(Java实例) 该篇Blog和上一篇(C++实例)基本相同,只是面向于我们团队中的Java工程师,毕竟我们项目的前端部分是基于Android开发的,而且我们研发 ...

  7. java基础(十五)----- Java 最全异常详解 ——Java高级开发必须懂的

    本文将详解java中的异常和异常处理机制 异常简介 什么是异常? 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常. Java异常的分类和类结构图 1.Java中的所 ...

  8. 「跬步千里」详解 Java 内存模型与原子性、可见性、有序性

    文题 "跬步千里" 主要是为了凸显这篇文章的基础性与重要性(狗头),并发编程这块的知识也确实主要围绕着 JMM 和三大性质来展开. 全文脉络如下: 1)为什么要学习并发编程? 2) ...

  9. 异常处理器详解 Java多线程异常处理机制 多线程中篇(四)

    在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ...

随机推荐

  1. 时间工具类之“ JDK1.8中 LocalDate、LocalTime、LocalDateTime、LocalDateTimeUtil四个时间工具类”

    一.使用的原因 在JDK8发布的时候,推出了LocalDate.LocalTime.LocalDateTime这个三个时间处理类,以此来弥补之前的日期时间类的不足,简化日期时间的操作. 在Java8之 ...

  2. Leetcode刷题之链表增加头结点的前缀节点

    链表之增加头结点的前缀节点 在许多链表题中往往需要在题目给的头结点之前增加一个前缀节点 通常在删除链表和头结点需要交换时需要用到这一操作 因为增加这个节点就避免了对删除头结点这种特殊情况的特殊处理 而 ...

  3. Quantum CSS,一个超快的CSS引擎

    开始 本文翻译自Inside a super fast CSS engine: Quantum CSS,如果想要阅读原文,可以点击前往,以下内容夹杂本人一些思考,翻译也并不一定完全. 碎碎念 为什么翻 ...

  4. 记录axios高效率并发的方法

    //  首先我的请求是统一管理 方便创建拦截器 export function login(parameter) {   return axios({     url: api.Login,      ...

  5. 解决Mui中popover 顶部弹出菜单弹出位置不准确以及无法收回的问题

    前言 最近公司的项目转向使用Hbuilder开发移动端项目,其中想要通过在顶部标题栏加入弹出菜单的方式,来定位长列表的位置,如图所示. 问题 Mui的功能貌似还不是很完善,在使用这个弹出菜单的时候,发 ...

  6. dva+react+antd+webpack 项目开发配置

    如何搭建一个dva项目如何搭建一个dva项目 后期项目会在github上进行书写,同时也会在segmentfault上进行同步-3Q拜读-

  7. Java中使用最频繁及最通用的Java工具类

    在Java中,工具类定义了一组公共方法,Java中使用最频繁及最通用的Java工具类. 一. org.apache.commons.io.IOUtils closeQuietly:关闭一个IO流.so ...

  8. FastAPI(六十八)实战开发《在线课程学习系统》接口开发--用户 个人信息接口开发

    在之前的文章:FastAPI(六十七)实战开发<在线课程学习系统>接口开发--用户登陆接口开发,今天实战:用户 个人信息接口开发. 在开发个人信息接口的时候,我们要注意了,因为我们不一样的 ...

  9. LC-349

    Given two integer arrays nums1 and nums2, return an array of their intersection. Each element in the ...

  10. 前端CSS基础

    一:CSS 1.什么是CSS? CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素. 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化(渲染). C ...