permits 是 java 17 密封类机制中的关键字,用于在 sealed 类或接口声明末尾显式列出允许继承或实现的子类,仅作编译期继承控制,不授予权限、不影响运行时行为。

Java 中并没有 permits 子句。这是 Java 17 引入的 sealed classes(密封类) 特性中使用的关键词,但它的正确语法是 permits 出现在类声明的 extends 或 implements 之后,用于**明确列出哪些类可以继承或实现该密封类/接口**,而不是“指定许可类的作用与限制继承”这种模糊表述。
permits 关键字的真实作用
permits 是密封类机制的一部分,其核心目的是:在编译期就严格控制类的继承关系,防止任意扩展。它本身不赋予被列名类任何特殊能力,只是“放行名单”。
- 只有在
permits列表中显式写出的类,才被允许继承该sealed类(或实现sealed接口) - 未列入的类即使满足语法(如正确 extends),也会在编译时报错:
class X is not allowed to extend sealed class Y - 被允许的子类自身也必须声明自己的“继承策略”,例如声明为
final、sealed或non-sealed
permits 的典型写法与限制条件
它只能出现在 sealed 类或接口的声明末尾,且必须和 extends / implements 连用:
public sealed interface Shape permits Circle, Rectangle, Triangle { ... }
public sealed class Expression permits NumberExpr, AddExpr, MulExpr { ... }
- 被
permits列出的类必须与密封类在同一个模块(或同一包中,若未使用模块系统) - 不能使用通配符、正则或范围表达式;必须逐个写出具体类名
- 不允许跨模块隐式许可——若子类在另一模块,需通过
opens或exports配合模块声明显式开放
为什么不能靠 permits “授权功能”?
permits 不影响运行时行为,也不改变访问权限(如 private 成员仍不可见)。它仅是一道编译期“门禁”:
- 子类能否调用父类方法,取决于修饰符(
public/protected等),而非是否在permits中 - 子类能否覆盖某个方法,取决于该方法是否为
final,与permits无关 - 一个被许可的子类如果自己声明为
final,那它就彻底不可继承;如果声明为non-sealed,则可被任意类继承——permits对它不再设限
常见误用与注意事项
开发者容易混淆 permits 和传统面向对象中的“权限控制”或“策略授权”:
- ❌ 错误认知:“把类加进 permits 就能让它访问私有成员” → 实际上不能
- ❌ 错误认知:“permits 可以动态修改” → 它是编译期静态约束,无法反射绕过
- ✅ 正确用途:建模有限、可枚举的类型层次,比如 AST 节点、协议消息类型、状态机状态等
- ⚠️ 注意:IDE 或旧版 JDK(permits,需确认构建环境支持密封类
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











