我在switch表达式中覆盖了一个密封类的所有子类,但Java编译器仍然说该switch没有穷尽。为什么?

移动开发 2026-07-10

假设结构是:

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。这意味着你的层次结构允许 ShapeQuadrangle 的实例——它们并不是 RectangleDiamondCircle 之一。因此,你的switch并非穷尽。

至少有三种解决方案。我怀疑第一种最适合你的场景,也是你正在寻找的那个。

  1. ShapeQuadrangle 成为抽象的(无论是抽象类还是接口)

java abstract sealed class Shape permits Quadrangle, Circle {} abstract sealed class Quadrangle permits Rectangle, Diamond {} 2.在 switch中为 ShapeQuadrangle 增加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 -> {} }


  1. 在其他语言中,例如Kotlin,密封类确实是隐式抽象的。这可能是你困惑的原因。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章