0Pricing
Java Academy · 课时

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 反馈 — 无需本地设置。

此课程中的所有课时

  1. 声明密封类型
  2. permits 子句
  3. 使用 Record 实现密封类型
  4. 对密封类型使用穷尽式 switch
← 返回 Java Academy