一、Record 的诞生背景
Java 的 Record(记录类)是 Java 14 引入的预览特性,于 Java 16 正式标准化。其设计初衷是简化不可变数据类的定义,解决传统 POJO 类中大量样板代码(如构造器、getter、equals、hashCode、toString 等)的问题。例如,一个简单的 Person
类在传统写法中需要 30+ 行代码,而用 Record 只需一行。
传统类 vs Record 类:
// 传统 POJO(30+ 行)
public class Person {
private final int id;
private final String name;
// 构造器、getter、equals、hashCode、toString...
}
// Record 等效实现(1 行)
public record Person(int id, String name) {}
通过 Record,开发者可以专注于数据本身,而非重复的模板代码。
二、Record 的核心特性
-
不可变性
- Record 的所有字段默认是
final
的,创建后不可修改,天然线程安全。 - 适用于 DTO、配置项等需要数据一致性的场景。
- Record 的所有字段默认是
-
自动生成方法
- 编译器自动生成以下方法:
- 全参构造器
- 字段访问器(如
id()
、name()
,而非getId()
) equals()
、hashCode()
、toString()
。
- 编译器自动生成以下方法:
-
简洁语法
- 使用
record
关键字定义,语法紧凑:public record Point(int x, int y) {}
- 使用
-
限制性设计
- Record 类是隐式
final
的,不可被继承。 - 不能声明非静态实例字段(仅允许通过参数列表定义字段)。
- Record 类是隐式
三、Record 的基本用法
1. 定义与实例化
public record User(String username, String email) {}
// 实例化
User user = new User("Alice", "alice@example.com");
System.out.println(user.username()); // 输出 "Alice"
2. 自定义方法
Record 允许添加自定义方法:
public record Circle(double radius) {
// 计算面积
public double area() {
return Math.PI * radius * radius;
}
}
3. 参数校验(紧凑构造器)
通过紧凑构造器实现字段校验:
public record Email(String address) {
public Email {
if (!address.contains("@")) {
throw new IllegalArgumentException("Invalid email");
}
}
}
4. 实现接口与泛型
Record 可以实现接口,支持泛型:
public record Pair<T, U>(T first, U second) implements Serializable {
public String toJson() {
return "{ \"first\": \"" + first + "\", \"second\": \"" + second + "\" }";
}
}
四、Record 的进阶应用
-
替代 DTO/VO
- 快速定义 API 响应模型:
public record ApiResponse<T>(int code, String message, T data) {}
- 快速定义 API 响应模型:
-
模式匹配(Java 17+)
- 结合
instanceof
解构数据:Object obj = new Point(3, 4); if (obj instanceof Point(int x, int y)) { System.out.println("坐标: (" + x + ", " + y + ")"); }
- 结合
-
数据库映射
- 简化 JDBC 结果集处理:
try (ResultSet rs = statement.executeQuery()) { return new User(rs.getInt("id"), rs.getString("name")); }
- 简化 JDBC 结果集处理:
-
函数式编程
- 作为轻量级元组(如
Pair
、Triple
):record Pair<A, B>(A first, B second) {} List<Pair<String, Integer>> pairs = List.of(new Pair<>("Java", 1995));
- 作为轻量级元组(如
五、Record 与 Lombok 的对比
特性 | Record | Lombok |
---|---|---|
不可变性 | 默认支持 | 需手动添加 final |
代码生成 | 语言原生支持 | 依赖注解处理器 |
模式匹配 | 完全兼容 | 不支持 |
兼容性 | 需 JDK 16+ | 兼容旧版本 |
可变性 | 不可变 | 支持可变类(如 @Data ) |
选择建议:
- 优先 Record:需不可变类、使用模式匹配或 JDK 16+ 环境。
- 选择 Lombok:需可变类或兼容旧代码。
六、注意事项
-
不可继承性
- Record 不能继承其他类(隐式继承
java.lang.Record
)。
- Record 不能继承其他类(隐式继承
-
字段限制
- 所有字段必须通过参数列表声明,不支持动态添加实例字段。
-
序列化
- 需显式实现
Serializable
接口。
- 需显式实现
-
框架兼容性
- 部分框架(如旧版 Spring)可能需适配 Record 类型。
七、未来展望
- 模式匹配增强:与
sealed class
结合,构建更严格的类型系统。 - 框架整合:Spring 等框架或默认支持 Record 作为数据载体。
- 函数式扩展:与 Stream、Optional 深度结合,提升代码表现力。
总结
Java Record 通过极简语法和不可变性,显著减少了数据类的样板代码,同时提升了代码安全性和可维护性。其适用于 DTO、模式匹配、函数式编程等场景。