Java密封接口通过sealed+permits语法和编译器校验强制限定实现者,要求接口声明含permits子句列出具体类,且每个实现类必须用final/sealed/non-sealed之一修饰,并配合模块封装隐藏细节。

Java 中的密封接口(sealed interface)通过编译期强制约束,确保只有明确列出的类或接口能实现它。核心不是靠运行时检查,而是靠语法定义 + 编译器校验来“锁死”实现范围。
用 sealed + permits 明确列出可信实现者
接口声明必须同时包含 sealed 关键字和 permits 子句,后者列出所有被允许的直接实现类(或子接口):
-
permits后只能写已存在、可访问的具体类名,不能是通配符、变量或表达式 - 所有实现类必须与密封接口在同一个模块(推荐也在同一包),否则默认不可见
- 遗漏
permits或列表为空,编译直接报错:“sealed type must have a permits clause”
每个实现类必须声明自己的继承策略
仅在 permits 里出现还不够——每个被列出的类还必须用以下三者之一修饰自身:
-
final:最常用。表示该类不可被继承,彻底封住扩展链(如public final class Circle implements Shape) -
sealed:该类自己也限制子类,需配套自己的permits(适合分层建模,如sealed class Triangle implements Shape permits RightTriangle) -
non-sealed:开放继承,允许任意类继承它(慎用,会削弱整体密封性;仅在确实需要第三方扩展时考虑)
若未加这三者中任一修饰符,编译器会拒绝:“Class X is not allowed to extend sealed interface Y”。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
配合模块封装隐藏实现细节
密封性只管“谁可以实现”,不管“谁可以看到”。为防止反射或跨模块非法访问,需结合模块系统:
- 在
module-info.java中,只exports密封接口所在的包,不导出实现类所在包 - 避免在 API 返回值、参数或文档中暴露具体实现类类型,始终使用接口类型(如返回
Shape,而非Circle) - 如需反射(如测试),用
opens ... to精确授权,而非宽泛的opens
避免常见疏漏
实际开发中最容易踩坑的地方:
- 以为写了
permits就够了,忘了给实现类加final等修饰符 - 把实现类放在不同模块却没配置
requires和exports,导致编译找不到类 - 在
permits里写了类名但拼错(大小写、包名缺失),编译器无法解析 - 用
non-sealed开放某实现类后,又没控制好它的可见性,导致意外继承

















