186. Java 模式匹配 - Java 21 新特性:Record Pattern(记录模式匹配)
Java 在 SE 16 中引入了 record
(记录类)作为简洁表示不可变数据的方式。而在 Java 21 ,记录又进化了一个层次------引入了 Record Pattern(记录模式匹配)!
这意味着我们可以直接在 if
或 switch
中解构 record
类型,提取其中的字段,写出更干净、更具表达力的代码。
✅ 回顾:什么是 Record?
java
public record Point(int x, int y) {}
等价于一个包含:
- 两个字段
x
和y
- 对应的访问器
x()
和y()
- 自动生成的构造函数和
equals()
、hashCode()
、toString()
方法
🎯 什么是记录模式(Record Pattern)?
记录模式允许你使用结构匹配语法,直接从 record
中解构并提取字段。
🌰 示例:基本模式匹配
java
Object o = new Point(3, 4);
if (o instanceof Point(int x, int y)) {
System.out.println("x = " + x + ", y = " + y);
}
✨ 说明:
o instanceof Point(int x, int y)
不只是判断o
是Point
,还将其解构为x
和y
x
和y
是自动绑定的局部变量
🧠 深入理解:记录模式的行为规则
✅ 1. 使用的是"规范构造函数"
record
可以声明多个构造函数- 但记录模式始终基于那个由编译器自动生成的"规范构造函数"
java
record Point(int x, int y) {
Point(int x) {
this(x, 0);
}
}
下面这段代码无法编译:
java
Object o = ...;
// ❌ 不合法:没有 Point(int) 这种结构可匹配
if (o instanceof Point(int x)) {}
✅ 2. 你可以使用 var
做类型推断
java
record Point(double x, double y) {}
Object o = new Point(1.1, 2.2);
if (o instanceof Point(var x, var y)) {
System.out.println("类型被推断为 double: " + x + ", " + y);
}
✅ 3. 记录模式可以嵌套!
你可以在一个 record 中匹配另一个 record。
java
record Point(double x, double y) {}
record Circle(Point center, double radius) {}
Object o = new Circle(new Point(1.0, 2.0), 5.0);
if (o instanceof Circle(Point(var x, var y), var radius)) {
System.out.printf("圆心:(%f, %f), 半径:%f%n", x, y, radius);
}
💡 嵌套记录的结构匹配就像解包"洋葱层"。
✅ 4. 可与 switch 配合使用
java
record Box(Object o) {}
Object o = new Box("hello");
String result = switch (o) {
case Box(String s) -> "字符串:" + s;
case Box(Integer i) -> "整数:" + i;
default -> "其他类型";
};
System.out.println(result);
⚠️ 注意事项与坑点提醒
❌ 不支持装箱/拆箱转换
java
record Point(Integer x, Integer y) {}
Object o = new Point(1, 2);
// ❌ 无法将 Integer 自动解构为 int
if (o instanceof Point(int x, int y)) {
}
你必须匹配 相同类型,不能依赖自动装箱/拆箱。
❌ 不支持不可能的类型匹配
java
record Box(CharSequence o) {}
Object o = new Box("Java");
// ❌ Integer 不是 CharSequence 的子类,编译报错
switch (o) {
case Box(String s) -> System.out.println("字符串:" + s);
case Box(Integer i) -> System.out.println("整数:" + i);
default -> System.out.println("其他类型");
}
⚠️ 所有模式类型必须是组件类型的 子类型或相同类型,否则编译错误。
🔥 补充实战场景
🎨 构建坐标系统中的图形识别
java
record Point(int x, int y) {}
record Rectangle(Point topLeft, Point bottomRight) {}
Object shape = new Rectangle(new Point(0, 0), new Point(10, 10));
if (shape instanceof Rectangle(Point(int x1, int y1), Point(int x2, int y2))) {
System.out.printf("矩形范围:(x1=%d, y1=%d) 到 (x2=%d, y2=%d)%n", x1, y1, x2, y2);
}
🧾 小结
功能 | 描述 |
---|---|
✅ 记录模式 | 支持 record 的结构解构和字段绑定 |
📦 类型推断 | 支持 var 自动推断字段类型 |
🧱 支持嵌套 | 可用于深层嵌套的记录结构 |
💥 类型安全 | 匹配的类型必须是字段的子类型或相同类型 |
⚠️ 限制 | 不支持装箱/拆箱,不支持非规范构造函数结构匹配 |
🎓 建议练习:
- 尝试用记录模式重写你的
DTO
判断逻辑 - 编写带嵌套记录结构的
switch
分支逻辑 - 结合
sealed class + record pattern
创建结构化的业务处理模型