permits 子句
列出允许的子类型
permits 子句 是 CoddyKit 上的免费 Java Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
许可子句
permits 子句用于让密封类型列出允许的子类型。它紧跟在类型名称和 permits 关键字之后。
基本语法
在 permits 之后用逗号分隔列出允许的子类型。
public class Main {
sealed interface Vehicle permits Car, Truck, Motorcycle {}
record Car() implements Vehicle {}
record Truck() implements Vehicle {}
record Motorcycle() implements Vehicle {}
public static void main(String[] args) {
Vehicle v = new Truck();
System.out.println(v.getClass().getSimpleName());
}
}实现约定
每个命名的子类型都必须实际通过 implements(对于接口)或 extends(对于类)继承或实现密封类型。在 permits 中列出一个并未如此做的类,会导致编译错误。
省略许可列表
如果所有允许的子类型都与密封类型声明在同一个文件中,您可以完全省略 permits。编译器会自动推断这个列表。
public class Main {
sealed interface Status {}
record Active() implements Status {}
record Inactive() implements Status {}
public static void main(String[] args) {
Status s = new Active();
System.out.println(s.getClass().getSimpleName());
}
}何时必须指定许可列表
如果子类型位于同一包或模块中的不同文件内,就必须在 permits 中明确列出它们。编译器无法跨文件推断这些类型。
顺序并不重要
permits 中名称的顺序没有语义含义。它不会影响分支选择行为或其他任何内容;它只是一个允许类型的列表。
带许可列表的类继承层次
同一个子句也适用于包含抽象行为的密封类。
public class Main {
sealed static abstract class Node permits Leaf, Branch {
abstract int size();
}
static final class Leaf extends Node {
int size() { return 1; }
}
static final class Branch extends Node {
final Node a, b;
Branch(Node a, Node b) { this.a = a; this.b = b; }
int size() { return a.size() + b.size(); }
}
public static void main(String[] args) {
Node tree = new Branch(new Leaf(), new Branch(new Leaf(), new Leaf()));
System.out.println("Leaves: " + tree.size());
}
}遗漏子类型
如果某个类实现了密封接口,却没有出现在 permits 中,编译就会失败,并显示该类不允许继承或实现密封类型的消息。
允许的类型是公开信息
permits 列表是类型约定的一部分,并会记录在类文件中。工具和编译器可以读取它,从而知道完整的子类型集合。
混合使用 final 和密封子类型
permits 列表可以混合使用不同的修饰符:某些子类型使用 final,其他子类型使用 sealed 以继续向更深层次扩展继承层次。
public class Main {
sealed interface Shape permits Circle, Polygon {}
record Circle(double r) implements Shape {}
sealed interface Polygon extends Shape permits Triangle, Rectangle {}
record Triangle() implements Polygon {}
record Rectangle() implements Polygon {}
public static void main(String[] args) {
Shape s = new Triangle();
System.out.println(s instanceof Polygon);
}
}最佳实践
为了提高可读性,请让密封类型及其子类型彼此靠近。对于小型的单文件继承层次,优先省略 permits;当代码拆分到多个文件时,再明确列出这些类型。
快速检查
请检验您对许可子句的理解。
回顾
您学会了使用 permits 子句。
- 它会在密封类型名称之后列出允许的子类型。
- 每个列出的类型都必须继承或实现密封类型。
- 当所有子类型位于同一个文件中时,可以省略它。
- 子类型本身也可以是密封类型,从而继续扩展继承层次。
常见问题解答
「permits 子句」课时是免费的吗?
是的 — 「permits 子句」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「permits 子句」这节课中我会学到什么?
列出允许的子类型 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「permits 子句」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 声明密封类型
- permits 子句
- 使用 Record 实现密封类型
- 对密封类型使用穷尽式 switch