Java Feature - Sealed
概述
- 封闭类在 JDK 17 正式发布
OOP
问题根源 - 无限制的扩展性
限制可扩展性
- OOP 的最佳实践 - 把可扩展性限制在可控范围,而不是无限的扩展性
- 继承的安全缺陷
- 一个可扩展的类,子类和父类可能会相互影响,导致不可预知的行为
- 涉及敏感信息的类,增加可扩展性并非优先选项,尽量避免父类或者子类的影响
- 设计 API
- 一个类,如果没有真实的可扩展需求,使用 final 修饰符
- 一个方法,子类如果没有重写的必要性,使用 final 修饰符
- 限制不可预测的可扩展性,可以实现代码的安全性和健壮性
- 在 JDK 17 之前,限制可扩展性的两种方法 - 使用私有类或者 final 修饰符
- 私有类不是公开接口,只能内部使用,而 final 修饰符彻底放弃了可扩展性
- 可扩展性 - 全开放 or 全封闭
- 从 JDK 17 开始
- 使用类修饰符 sealed 修饰的类是封闭类,使用类修饰符 sealed 修饰的接口是封闭接口
- 封闭类和封闭接口 - 限制可以扩展或实现它们的其它类或接口
- 把可扩展性限制在可控范围
封闭类
- 被扩展的父类称为封闭类,扩展而来的子类称为许可类
- 使用类修饰符 sealed 声明封闭类
- 在所有的 extends 和 implements 语句之后,使用 permits 指定允许扩展该封闭类的子类
- 由 permits 关键字指定的许可子类,必须和封闭类处于同一个 module 或者 package
- 如果封闭类和许可类在同一个 module 中,它们可以处于不同的 package
- 如果允许许可子类和封闭类在同一个源码文件中,封闭类可以不使用 permits 语句
- 编译器将检索源码文件,在编译期为封闭类添加上许可子类
- 最佳实践 - 总是使用 permits 语句 - 语义明确 + 可读性强
许可类
约束
- 许可类必须和封闭类处于同一 module 或者 package - 在编译期间,封闭类可以访问它的许可类
- 许可类必须是封闭类的直接扩展类 - 许可类不具备传递性
- 许可类必须声明是否继续保持封闭
- 许可类可以声明为终极类(final),关闭扩展性
- 许可类可以声明为封闭类(sealed),延续受限的扩展性
- 许可类可以声明为解封类(non-sealed),支持不受限制的扩展性
Circle 是解封类,Square 是封闭类,ColoredSquare 是终极类
ColoredCircle 既不是封闭类,也不是许可类Square 是 Shape 的许可类,ColoredSquare 是 Square 的许可类,但 ColoredSquare 并非 Shape 的许可类
限定优先级
由高到低
- 使用私有类
- 使用 final 修饰符
- 使用 sealed 修饰符
- 不受限制的扩展性
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.