对密封类型使用穷尽式 switch
编译时完整性检查
对密封类型使用穷尽式 switch 是 CoddyKit 上的免费 Java Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
穷举式分支选择
当您针对密封类型使用 switch 时,编译器知道每个允许的子类型。如果分支选择覆盖了所有子类型,它就是穷举式的,您不需要默认分支。
类型模式分支选择
分支选择表达式可以使用类型模式,根据密封值的运行时类型进行匹配。
public class Main {
sealed interface Shape permits Circle, Square {}
record Circle(double radius) implements Shape {}
record Square(double side) implements Shape {}
static String describe(Shape s) {
return switch (s) {
case Circle c -> "circle r=" + c.radius();
case Square sq -> "square s=" + sq.side();
};
}
public static void main(String[] args) {
System.out.println(describe(new Circle(2)));
System.out.println(describe(new Square(3)));
}
}无需默认分支
由于 Circle 和 Square 是唯一允许的子类型,编译器会接受这个完整的分支选择。添加 default 会显得多余。
编译时完整性
如果之后添加了新的允许子类型,却忘记处理它,那么每个穷举式分支选择都会无法编译。这样可以将一整类运行时错误转变为编译错误。
计算 Result
穷举式分支选择表达式非常适合将一个值归约为 area 等结果。
public class Main {
sealed interface Shape permits Circle, Square {}
record Circle(double radius) implements Shape {}
record Square(double side) implements Shape {}
static double area(Shape s) {
return switch (s) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Square sq -> sq.side() * sq.side();
};
}
public static void main(String[] args) {
System.out.printf("%.2f%n", area(new Circle(1)));
System.out.printf("%.2f%n", area(new Square(2)));
}
}分支选择语句与表达式的区别
完整覆盖适用于分支选择表达式(能够产生值的分支选择)以及在密封类型上使用箭头形式的分支选择语句。编译器会强制要求覆盖所有情况。
处理空值
默认情况下,如果引用类型上的分支选择接收到空值,就会抛出 NullPointerException。您可以添加 case null 标签来明确处理空值。
public class Main {
sealed interface Shape permits Circle, Square {}
record Circle(double radius) implements Shape {}
record Square(double side) implements Shape {}
static String describe(Shape s) {
return switch (s) {
case null -> "no shape";
case Circle c -> "circle";
case Square sq -> "square";
};
}
public static void main(String[] args) {
System.out.println(describe(null));
System.out.println(describe(new Circle(1)));
}
}守卫不会破坏穷举完整性
您可以添加 when 守卫来细化分支,但单独使用带守卫的分支并不能覆盖某个类型。要保持穷举完整性,您仍然需要为每个子类型提供不带守卫的分支。
public class Main {
sealed interface Shape permits Circle, Square {}
record Circle(double radius) implements Shape {}
record Square(double side) implements Shape {}
static String size(Shape s) {
return switch (s) {
case Circle c when c.radius() > 10 -> "big circle";
case Circle c -> "small circle";
case Square sq -> "square";
};
}
public static void main(String[] args) {
System.out.println(size(new Circle(20)));
System.out.println(size(new Circle(2)));
}
}对密封类执行分支选择
同样的穷举完整性也适用于密封类,而不仅仅是接口。
public class Main {
sealed static abstract class Token permits Word, Number {}
static final class Word extends Token { final String text; Word(String t){text=t;} }
static final class Number extends Token { final int value; Number(int v){value=v;} }
static String show(Token t) {
return switch (t) {
case Word w -> "word:" + w.text;
case Number n -> "num:" + n.value;
};
}
public static void main(String[] args) {
System.out.println(show(new Word("hi")));
System.out.println(show(new Number(7)));
}
}为什么这很强大
穷举式分支选择与密封类型结合后,可以让代码既安全又易于演进。所有情况都记录在同一个位置,当模型扩展时,编译器会保证您不会遗漏任何情况。
完整示例
这里将一个密封结果类型归约为一条消息,并完整覆盖所有情况。
public class Main {
sealed interface Result permits Ok, Err {}
record Ok(int value) implements Result {}
record Err(String message) implements Result {}
static String render(Result r) {
return switch (r) {
case Ok ok -> "value = " + ok.value();
case Err err -> "error: " + err.message();
};
}
public static void main(String[] args) {
System.out.println(render(new Ok(10)));
System.out.println(render(new Err("bad input")));
}
}快速检查
请检验您对穷举式分支选择的理解。
回顾
您学会了在密封类型上使用穷举式分支选择。
- 覆盖所有允许的子类型会使分支选择具有穷举性,因此不需要
default。 - 遗漏新的子类型会变成编译错误。
case null可以明确处理空值。- 守卫可以细化分支,但不能替代不带守卫的分支。
用 AI 导师学习 Java — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 104
- 课程
- 374
常见问题解答
「对密封类型使用穷尽式 switch」课时是免费的吗?
是的 — 「对密封类型使用穷尽式 switch」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「对密封类型使用穷尽式 switch」这节课中我会学到什么?
编译时完整性检查 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「对密封类型使用穷尽式 switch」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 声明密封类型
- permits 子句
- 使用 Record 实现密封类型
- 对密封类型使用穷尽式 switch