Java 21 对 模式匹配的 switch
表达式和语句 进行了进一步增强,这是在 Java 17 和 Java 19 中引入的初步模式匹配功能的基础上的重大改进。这一特性旨在使 switch
更加灵活、强大,并支持更复杂的类型检查和数据解构操作。
以下是 Java 21 中模式匹配的 switch
表达式和语句增强的关键点:
1. 增强的模式匹配能力
Java 21 的 switch
表达式和语句支持更丰富的模式匹配形式,包括:
- 类型测试模式(Type Test Pattern) :用于检查对象是否属于某种类型。
- 记录模式(Record Pattern) :用于解构记录类的对象。
- 嵌套模式(Nested Patterns) :支持在同一个
case
中使用多个模式。
示例:
假设我们有以下类层次结构和记录类:
java
sealed interface Shape permits Circle, Rectangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
我们可以使用增强的 switch
来处理这些类型:
scss
double area = switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
};
System.out.println("Area: " + area);
2. 支持记录模式(Record Patterns)
记录模式允许在 switch
中直接解构记录类的对象,从而避免显式的字段访问。
示例:
csharp
record Point(int x, int y) {}
void printPointInfo(Object obj) {
switch (obj) {
case Point(int x, int y) when x == y -> System.out.println("Diagonal point at (" + x + ", " + y + ")");
case Point(int x, int y) -> System.out.println("Point at (" + x + ", " + y + ")");
default -> System.out.println("Not a point");
}
}
解释:
- 在
case Point(int x, int y)
中,Point
类型的对象被自动解构成x
和y
。 - 可以结合守卫条件(
when
子句)进行额外的逻辑判断。
3. 支持嵌套模式(Nested Patterns)
嵌套模式允许在一个 case
中组合多个模式,从而实现更复杂的匹配逻辑。
示例:
假设我们有一个嵌套的记录类:
scss
record Box(Shape shape) {}
我们可以使用嵌套模式来解构 Box
和其内部的 Shape
:
csharp
double calculateArea(Box box) {
return switch (box) {
case Box(Circle c) -> Math.PI * c.radius() * c.radius();
case Box(Rectangle r) -> r.width() * r.height();
};
}
解释:
case Box(Circle c)
匹配一个包含Circle
的Box
,并将其解构成c
。- 这种嵌套模式可以递归地解构复杂的数据结构。
4. 守卫条件(Guarded Patterns)
守卫条件允许在 case
中添加额外的布尔表达式,以进一步限制匹配的条件。
示例:
csharp
void checkNumber(Object obj) {
switch (obj) {
case Integer i when i > 0 -> System.out.println("Positive integer: " + i);
case Integer i -> System.out.println("Non-positive integer: " + i);
default -> System.out.println("Not an integer");
}
}
解释:
when i > 0
是一个守卫条件,只有当i > 0
为真时,才会匹配该分支。
5. 默认行为与穷尽性检查
在 switch
表达式中,所有可能的情况都必须被覆盖,否则会导致编译错误。这种设计确保了代码的健壮性。
示例:
java
sealed interface Shape permits Circle, Rectangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
double area = switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
// 缺少 default 会报错,因为 Shape 是密封类
};
注意:
- 如果
Shape
是密封类(Sealed Class),编译器可以推断出所有可能的子类型,因此default
分支可以省略。 - 如果
Shape
不是密封类,则需要显式地添加default
分支。
6. 箭头语法与传统语法的混合使用
Java 21 允许在同一个 switch
中混合使用箭头语法(->
)和传统语法(:
)。这提供了更大的灵活性。
示例:
csharp
void printDay(String day) {
switch (day) {
case "MONDAY" -> System.out.println("Start of the work week");
case "FRIDAY":
System.out.println("End of the work week");
break;
default:
System.out.println("Midweek days");
break;
}
}
解释:
- 使用箭头语法的分支不需要
break
。 - 使用传统语法的分支仍需要手动添加
break
。
7. 总结与优势
- 更简洁的代码:
- 使用模式匹配和箭头语法,减少了冗余的类型转换和
break
语句。 - 直接解构对象,避免了显式的字段访问。
- 更强大的表达能力:
- 支持记录模式、嵌套模式和守卫条件,能够处理复杂的类型和数据结构。
- 提高安全性:
- 编译器的穷尽性检查确保了所有可能的情况都被覆盖,减少了遗漏分支的风险。
- 更好的可读性:
- 通过清晰的模式匹配逻辑,使代码更加直观,易于理解和维护。
适用场景
- 复杂的数据结构:如嵌套的记录类或密封类。
- 多态对象处理:如处理继承关系或接口实现。
- 简化条件逻辑 :替代传统的
if-else
或switch
语句,尤其在需要类型检查和解构时。
通过这些增强,Java 21 的 switch
表达式和语句变得更加现代化,能够更好地适应现代开发需求,同时提高了代码的简洁性和安全性。