你不知道的Java 新技术:封闭类

我们使用了 Java 语言来讨论继承的问题,其实这是一个面向对象机制的普遍的问题,甚至它也不单单是面向对象语言的问题,比如使用 C 语言的设计和实现,也存在类似的问题。

由于继承的安全问题,我们在设计 API 时,有两个要反省思考的问题

  • 一个类,有没有真实的可扩展需求,能不能使用 final 修饰符?
  • 一个方法,子类有没有重写的必要性,能不能使用 final 修饰符?

限制住不可预测的可扩展性,是实现安全代码的一个重要目标。

目前而言,限制住可扩展性只有两个方法,使用私有类或者 final 修饰符。显而易见,私有类不是公开接口,只能内部使用。而 final 修饰符彻底放弃了可扩展性。要么全开放,要么全封闭,可扩展性只能在可能性的两个极端游走。全封闭彻底没有了可扩展性,全开放又面临固有的安全缺陷,这种二选一的状况有时候很让人抓狂,特别是设计公开接口的时候。

通过把可扩展性的限制在可以预测和控制的范围内,封闭类打开了全开放和全封闭两端之间的中间地带,为接口设计和实现提供了新的可能性。

我一点都不会奇怪,这一项技术很快、很快、很快就会被大面积采用。因为,苦可扩展性久矣!你大概可以猜到,我为什么这么着急地要聊聊封闭类了。

怎么使用封闭类?

怎么声明封闭类

封闭类的声明使用 sealed 类修饰符,然后在所有的 extendsimplements 语句之后__使用 permits 指定允许扩展该封闭类的子类。 比如:

public sealed class Shape permits Circle, Rectangle, Square { …``}

复制代码

permits 关键字指定的许可子类(permitted subclasses),必须和封闭类处于同一模块(module)或者包空间(package)里。如果允许扩展的子类和封闭类在同一个源代码文件里,封闭类可以不使用 permits 语句,Java 编译器将检索源文件,在编译期为封闭类添加上许可的子类。 比如下面的两种 Shape 封闭类的声明具有一样的运行时效果:

sealed class Shape { …``}`

private final class Circle extends Shape { ...``}

private final class Rectangle extends Shape { ...``}

private final class Square extends Shape { `…``}

复制代码

sealed class Shape permits Circle, Rectangle, Square { …``}`

private final class Circle extends Shape { ...``}

private final class Rectangle extends Shape { ...``}

private final class Square extends Shape { `…``}

复制代码

怎么声明许可类

许可类的声明需要满足下面的三个条件:

  1. 在编译期,封闭类和封闭接口必须可以访问它的许可类;

  2. 许可类必须是封闭类或者封闭接口的直接扩展类或者直接实现类;

  3. 许可类必须声明是否继续保持封闭。

  • 许可类可以声明为_终极_类_(final)_,从而关闭扩展性;

  • 许可类可以声明为封闭类_(sealed)_,从而延续受限制的扩展性;

  • 许可类可以声明为解封类_(non-sealed)_, 从而支持不受限制的扩展性。

比如下面的例子中,许可类 Circle 是终极类,Rectangle 是封闭类,Square 是解封类。

sealed class Shape permits Circle, Rectangle, Square { …``}`

private final class Circle extends Shape { ...``}

private sealed class Rectangle extends Shape permits TransparentRectangle, FilledRectangle{ ...``}

private non-sealed class Square extends Shape { `…``}

复制代码

需要注意的是,由于许可类必须是封闭类的直接扩展,因此许可类不具备传递性。也就是说,上面的例子中,TransparentRectangleRectangle 的许可类,但不是 Shape 的许可类。

怎么判断许可类?

我们有时候需要判断一个封闭类声明的变量,是由哪一个子类实现的。由于许可类是子类的一个类型,我们的当然可以使用 instanceof 关键字。

Shape flip(Shape shape) { if (shape instanceof Circle) { return shape; } else if (shape instanceof Rectangle) { return shape.flip(); } else if (shape instanceof Square) { return shape; }``}

复制代码

不过,由于在编译期,封闭类已经知道了它所有的许可类,许可类的判断可以有更皮实的用法。上面的例子中,如果漏掉某一个 if-else 语句,编译器都不会报错。当然,也不应该报错。这其实也是一种的类的继承机制带来的常见问题。

不受限制的扩展性,使得我们没有办法穷举可能的子类。因此,不论我们怎么努力,我们都没有办法控制可扩展类的安全性和健壮性。封闭类为我们更好地控制子类提供了新的可能性。

通过和型式测试(JEP 375,我们以后有时间聊聊这个新技术)技术的结合,编译器可以帮助我们检查穷举所有的许可类。比如,下面的例子中,如果遗漏掉了某一个 case 语句,编译器就会报错。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

针对以上面试题,小编已经把面试题+答案整理好了

最新大厂必问微服务面试题汇总:SpringCloud、Boot、Dubbo

最新大厂必问微服务面试题汇总:SpringCloud、Boot、Dubbo

最新大厂必问微服务面试题汇总:SpringCloud、Boot、Dubbo

面试专题

image

除了以上面试题+答案,小编同时还整理了微服务相关的实战文档也可以分享给大家学习

image

image

image
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
g-W9FHCMs4-1713519249046)]

[外链图片转存中…(img-1WSeMN2w-1713519249046)]

[外链图片转存中…(img-fc5WPi8y-1713519249047)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 27
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值