在日常 Java 开发中,我们经常需要编写只用于承载数据、不包含业务逻辑的类,比如接口入参、出参、DTO、VO、POJO 等。传统写法需要手动生成构造器、getter、equals ()、hashCode ()、toString () 方法,即便用 Lombok 简化,仍存在代码冗余、语义不清晰等问题。
Java 16 正式推出的Record特性,就是为了解决这个痛点而生的极简数据载体。它能让我们用一行代码定义完整的数据类,自动生成所有模板方法,大幅提升开发效率和代码可读性。
本文将带你从零掌握 Record 的用法,对比传统写法的优劣,结合实战场景教你如何用 Record 优雅优化 Java 数据载体。
二、传统数据类的痛点
先回顾一下我们最熟悉的传统 Java 数据类写法(以用户信息 DTO 为例):
java
运行
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 传统用户数据载体
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {
// 用户ID
private Long userId;
// 用户名
private String username;
// 年龄
private Integer age;
}
即便依赖 Lombok 的
@Data注解,依旧存在这些问题:- 代码冗余:需要添加多个注解,无业务逻辑却依赖第三方库;
- 语义模糊:无法直观体现「这是一个纯数据载体」;
- 可变性风险:默认生成 setter,数据可被篡改,不符合不可变数据设计;
- 维护成本:字段增减时,需重新生成 / 调整模板方法,容易遗漏。
如果不使用 Lombok,手动编写所有方法,代码量会直接翻倍,可读性极差。
三、Record 核心概念
1. 什么是 Record?
Record 是 Java 16 引入的特殊类,专门用于表示不可变的数据载体。它是一种语法糖,编译器会自动生成以下核心成员:
- 私有 final 实例字段
- 全参构造器
- 与字段名同名的 getter 方法(无 get 前缀)
- equals () 和 hashCode () 方法
- toString () 方法
2. Record 核心特性
- 不可变性:字段默认
private final,无 setter 方法,线程安全; - 极简语法:无需编写模板代码,一行定义数据类;
- 语义清晰:关键字
record直接表明「纯数据载体」; - 无继承:Record 默认继承
java.lang.Record,无法继承其他类; - 实现接口:可以实现任意接口,兼容业务扩展。
四、Record 基础用法
1. 最简定义:一行搞定数据类
用 Record 重写上面的
UserDTO,无需任何注解、无需第三方库:java
运行
/**
* Record 优化后的用户数据载体
* @param userId 用户ID
* @param username 用户名
* @param age 年龄
*/
public record UserRecord(Long userId, String username, Integer age) {
}
✅ 效果:编译器自动生成所有模板方法,代码量减少 90%!
2. 核心方法自动生成
我们直接测试这个 Record 类:
java
运行
public class RecordTest {
public static void main(String[] args) {
// 1. 全参构造器创建对象
UserRecord user = new UserRecord(1001L, "Java开发者", 25);
// 2. 无get前缀,直接用字段名访问数据
System.out.println(user.userId());
System.out.println(user.username());
System.out.println(user.age());
// 3. 自动生成的toString()
System.out.println(user);
// 4. 自动生成的equals()/hashCode()
UserRecord user2 = new UserRecord(1001L, "Java开发者", 25);
System.out.println(user.equals(user2)); // true:值比较,非引用比较
}
}
输出结果:
plaintext
1001
Java开发者
25
UserRecord[userId=1001, username=Java开发者, age=25]
true
3. 自定义扩展(不破坏核心特性)
Record 并非完全不可扩展,支持以下合理定制:
(1)紧凑构造器(参数校验)
java
运行
public record UserRecord(Long userId, String username, Integer age) {
// 紧凑构造器:无需重复写参数,自动校验
public UserRecord {
// 非空校验
if (userId == null || username == null) {
throw new IllegalArgumentException("用户ID和用户名不能为空");
}
// 年龄合法性校验
if (age < 0 || age > 150) {
throw new IllegalArgumentException("年龄不合法");
}
}
}
✅ 优势:无需编写全参构造器,直接在紧凑构造器中做数据校验。
(2)自定义方法
java
运行
public record UserRecord(Long userId, String username, Integer age) {
// 自定义业务方法
public boolean isAdult() {
return this.age >= 18;
}
}
(3)实现接口
java
运行
// 实现序列化接口(分布式/接口传输必备)
public record UserRecord(Long userId, String username, Integer age) implements Serializable {
}
五、Record VS 传统数据类:全方位对比
表格
| 特性 | 传统 Java 类(+Lombok) | Record(Java 16+) |
|---|---|---|
| 代码量 | 冗余,需注解 / 模板代码 | 极简,一行定义 |
| 不可变性 | 需手动控制 | 默认不可变,安全可靠 |
| 语义表达 | 模糊,无法区分数据类 | 清晰,record关键字 |
| 构造器 / 方法生成 | 依赖 Lombok / 手动生成 | 编译器自动生成 |
| 继承关系 | 可自由继承 | 仅继承java.lang.Record |
| 适用场景 | 通用类、业务类 | 纯数据载体(DTO/VO/POJO) |
核心结论:纯数据载体场景,Record 全面优于传统写法。
六、实战:Record 优化项目常用数据载体
在实际开发中,Record 可直接替代以下场景:
1. 接口响应 VO
java
运行
/**
* 统一接口响应VO
*/
public record ResultVO<T>(Integer code, String msg, T data) {
// 静态工厂方法:简化成功响应
public static <T> ResultVO<T> success(T data) {
return new ResultVO<>(200, "操作成功", data);
}
// 静态工厂方法:简化失败响应
public static <T> ResultVO<T> fail(String msg) {
return new ResultVO<>(500, msg, null);
}
}
2. 数据库查询 DTO
java
运行
/**
* 订单查询DTO
*/
public record OrderQueryDTO(Long orderId, String orderNo, LocalDateTime createTime) {
}
3. 方法返回多值(替代 Map)
java
运行
// 传统:用Map返回多值,类型不安全
// 优化:用Record返回多值,类型安全、语义清晰
public record UserStat(Long userId, Long loginCount, LocalDateTime lastLoginTime) {}
public UserStat getUserStat(Long userId) {
// 业务查询...
return new UserStat(userId, 100L, LocalDateTime.now());
}
七、Record 使用注意事项
-
不可变性是双刃剑
Record 没有 setter 方法,适合只读、不可变的数据。如果需要频繁修改字段,仍用传统类。
-
版本要求
Record 是 Java 16 + 特性,JDK 版本低于 16 无法使用。
👉 兼容方案:项目升级 JDK16+(目前主流 JDK17、21 均长期支持)。
-
无法继承其他类
Record 默认继承
java.lang.Record,Java 不支持多继承,因此不能再继承其他类,但可以实现接口。 -
字段默认 final
所有字段都是
private final,无法修改,符合不可变数据设计原则。
八、总结
Java Record 是纯数据载体的最优解,它彻底解决了传统数据类代码冗余、语义模糊、可变性风险等痛点:
- 极简代码:告别模板方法、告别 Lombok 注解;
- 安全可靠:默认不可变,线程安全,值比较更精准;
- 语义清晰:
record关键字一眼识别数据类; - 实战高效:直接替代 DTO、VO、POJO、方法多返回值等场景。
如果你的项目已经使用 JDK16+,立刻用 Record 重构所有数据载体,代码质量和开发效率会直接提升一个档次!
本文干货
- 传统数据类的 3 大核心痛点,Record 完美解决;
- Record 基础语法 + 扩展用法,开箱即用;
- 实战场景:接口 VO、查询 DTO、方法多返回值;
- 使用注意事项,避开踩坑。