在 Java 17 之前,使用传统的类层次结构来实现多态往往需要编写大量的 instanceof 检查或 switch 语句,并手工维护类之间的关系。自从 Java 15 引入了 sealed classes(封闭类)以及在 Java 17 强化了模式匹配(Pattern Matching),我们可以在保持代码安全、可读的同时,极大地简化多态实现。下面我们通过一个完整的示例来说明这一点。
1. 背景:传统多态实现的痛点
abstract class Shape { }
class Circle extends Shape { }
class Rectangle extends Shape { }
public double area(Shape s) {
if (s instanceof Circle c) {
return Math.PI * c.radius * c.radius;
} else if (s instanceof Rectangle r) {
return r.width * r.height;
} else {
throw new IllegalArgumentException("Unknown shape");
}
}
- 耦合度高:每新增一种形状,就需要在
area方法中加入新的分支。 - 可维护性差:业务逻辑与类型检查混在一起,阅读不够直观。
- 安全性不足:如果忘记处理某个子类,编译器不会提醒。
2. 使用 sealed 简化类层次
sealed 声明告诉编译器哪些子类是合法的,保证所有合法子类都已被列举:
public sealed abstract class Shape permits Circle, Rectangle {
// common properties or methods
}
public final class Circle extends Shape {
final double radius;
public Circle(double radius) { this.radius = radius; }
}
public final class Rectangle extends Shape {
final double width, height;
public Rectangle(double w, double h) { this.width = w; this.height = h; }
}
Circle与Rectangle必须被声明为final或者再次sealed(避免进一步派生)。- 编译器会强制检查
Shape的所有合法子类,防止遗漏。
3. 结合模式匹配的 switch 语法
Java 17 对 switch 语法进行了增强,允许我们在 switch 中直接使用模式匹配:
public double area(Shape s) {
return switch (s) {
case Circle c -> Math.PI * c.radius * c.radius;
case Rectangle r -> r.width * r.height;
};
}
- 简洁:不需要
instanceof语句。 - 安全:因为
Shape是sealed,编译器会检查所有分支是否已覆盖所有合法子类。若未覆盖,编译会报错。 - 可读:逻辑清晰,一眼就能看出每种形状的处理方式。
4. 进一步提升:使用 record 记录类
如果形状类仅仅是数据持有者,可以用 record 来简化定义:
public sealed record Shape permits Circle, Rectangle { }
public sealed record Circle(double radius) extends Shape { }
public sealed record Rectangle(double width, double height) extends Shape { }
record自动生成构造器、equals、hashCode、toString。- 代码更短、更易维护。
5. 小结
sealed:让类层次更明确,避免隐藏的子类导致的不可预期行为。- 模式匹配:让
switch语句更强大,直接在分支中解构对象。 record:提供更简洁的数据持有类,配合sealed可以快速搭建安全、易读的类型体系。
当你在项目中需要处理多态时,推荐先使用 sealed 来定义有限的子类集合,然后利用模式匹配的 switch 来实现业务逻辑。这样既能保持代码的安全性,也能显著提升可维护性和可读性。

发表回复