185. Java 模式匹配 - Java 21 新特性:Switch 的模式匹配
在 Java 21 中,Switch 模式匹配(Pattern Matching for switch) 正式成为标准功能,之前曾以预览形式出现在 Java 17–20。
这个特性将 switch 表达式和 instanceof 的模式匹配结合,极大增强了 Java 的表达力与可读性。
✅ 背景与目标
Java 中的 switch 语句原本只能匹配固定值(如整数、枚举、字符串)。但在许多情况下,我们更希望根据对象的类型执行不同的逻辑,这通常需要使用冗长的 if-else 结构。
来看一个典型的例子:
Object o = ...; // 任意对象
String formatted = null;
if (o instanceof Integer i) {
formatted = String.format("int %d", i);
} else if (o instanceof Long l) {
formatted = String.format("long %d", l);
} else if (o instanceof Double d) {
formatted = String.format("double %f", d);
} else {
formatted = String.format("Object %s", o.toString());
}
☀️ 用 Switch 模式匹配重写
使用 Java 21 的 Switch 模式匹配,上面的代码可以简洁地重写为:
Object o = ...;
String formatted = switch (o) {
case Integer i -> String.format("int %d", i);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %f", d);
default -> String.format("Object %s", o.toString());
};
🎯 你可以看到:
- 每个
case分支就像instanceof判断一样,自动完成类型转换。 - 代码更简洁清晰,无需强转(casting)。
⏱ 性能优势
使用 if-else 判断,性能是 O(n),分支越多,判断次数越多。
而 switch 使用的是 表驱动机制,可以达到 O(1) 的性能(理论上更快)。
🔍 支持的 case 标签类型
在 Java 21 中,switch 支持以下 case 标签:
- 原始整数类型:
byte,short,char,int - 对应包装类型:
Byte,Short,Character,Integer String- 枚举类型
- ✅ 类型模式(Type Patterns):如
case String s、case Point p等
🔐 受保护的 case 标签(Guarded Patterns)
我们有时不仅要匹配类型,还要加个附加条件。例如:对象是 String 且不为空。
以前只能写成 if 语句:
if (o instanceof String s && !s.isEmpty()) {
System.out.println("非空字符串:" + s);
}
在 switch 中能写吗?能!
Java 21 引入了 when 子句 —— 它允许我们在 case 中添加布尔条件:
String result = switch (o) {
case String s when !s.isEmpty() -> "Non-empty string: " + s;
case String s -> "Empty string";
default -> "Not a string";
};
✨ 语法解构:
case 类型 模式变量 when 条件表达式 -> 返回值;
这种写法称为 guarded case label(受保护的 case 标签),比传统写法更具表达力。
📦 更多示例
示例 1:处理多种数字类型
Object o = 3.14;
String result = switch (o) {
case Integer i -> "整数:" + i;
case Double d -> "小数:" + d;
case Number n -> "其他数字类型:" + n;
default -> "不是数字";
};
示例 2:配合记录类(Record)使用
record Point(int x, int y) {}
Object o = new Point(3, 4);
String result = switch (o) {
case Point p when p.x() == p.y() -> "这是一个对角点:" + p;
case Point p -> "普通点:" + p;
default -> "未知类型";
};
⚠️ 注意事项
case String s && !s.isEmpty()❌ 不合法switch不接受直接写布尔表达式- 正确用法是
case String s when !s.isEmpty() default分支仍是必须的,除非已穷尽所有可能
🧠 小结
| 特性 | 说明 |
|---|---|
| 🧩 类型匹配 | case 标签可是类型模式(如 case String s) |
| 🛡 受保护 case | 可以加上布尔条件 when 条件 |
| ⚡ 性能提升 | switch 是 O(1),更快 |
| 🔍 更清晰表达 | 减少冗余代码,提升可读性 |
| 📦 适配多种类型 | 支持数字、字符串、枚举、记录、对象类型等 |
🎓 推荐实战练习:
- 用 switch 模式匹配重构你项目中的
instanceof判断代码 - 尝试组合类型 + guard 条件
- 和
record结合使用进行数据拆解