我在switch表达式中覆盖了一个密封类的所有子类,但Java编译器仍然说该switch没有穷尽。为什么?
假设结构是:
sealed class Shape permits Circle, Quadrangle {}
sealed class Quadrangle extends Shape permits Diamond, Rectangle { }
final class Rectangle extends Quadrangle {}
final class Diamond extends Quadrangle {}
final class Circle extends Shape {}
然后当我遇到类似这样的switch语句:
switch (shape) {
case Rectangle _-> System.out.println("");
case Diamond _-> System.out.println("");
case Circle _-> System.out.println("");
}
我得到的信息是没有覆盖所有情况,并被迫实现 default。在我看来这像是一个错误之类的。事情不应该是那样。因为我已经覆盖了所有情况。
是否有办法让switch语句达到穷尽性?如果有,应该怎么做?
解决方案
在Java中,a sealed class并非隐式的abstract1。这意味着你的层次结构允许 Shape 和 Quadrangle 的实例——它们并不是 Rectangle、Diamond 或 Circle 之一。因此,你的switch并非穷尽。
至少有三种解决方案。我怀疑第一种最适合你的场景,也是你正在寻找的那个。
- 让
Shape和Quadrangle成为抽象的(无论是抽象类还是接口)
java
abstract sealed class Shape permits Quadrangle, Circle {}
abstract sealed class Quadrangle permits Rectangle, Diamond {}
2.在 switch中为 Shape 和 Quadrangle 增加cases
java
switch (shape) {
case Rectangle _ -> {}
case Diamond _ -> {}
case Circle _ -> {}
// Must put least specific types last
case Quadrangle _ -> {}
case Shape _ -> {}
}
3.在 switch中添加一个 default 的case
java
switch (shape) {
case Rectangle _ -> {}
case Diamond _ -> {}
case Circle _ -> {}
default -> {}
}
- 在其他语言中,例如Kotlin,密封类确实是隐式抽象的。这可能是你困惑的原因。