java 14 引入 record 预览特性,java 16 正式标准化,专为不可变数据载体设计,自动生成构造器、getter、equals、hashcode 和 tostring;支持定制构造器和静态方法,但不可继承、无 setter、不支持泛型推断构造器。

Java 14 引入 record 作为预览特性,Java 16 正式将其转为标准特性。它专为“不可变数据载体”设计,非常适合声明 DTO(Data Transfer Object)、VO(View Object)等纯数据结构,省去手写构造器、getter、equals、hashCode 和 toString 的繁琐工作。
Record 的核心语义:不可变、透明、仅数据
record 不是普通类,而是一种特殊的类声明形式,编译器会自动生成以下内容:
- 一个公共的、final 的、与 record 同名的构造器(参数顺序和字段声明一致)
- 每个组件(component)对应一个 public、final、同名的 getter 方法(无 get 前缀,如
name()而非getName()) - 自动实现
equals()、hashCode()和toString(),基于所有组件值 - 所有字段隐式为
final,且不可被继承(record 是final类)
例如,一个用户信息 DTO 可简洁定义为:
public record User(String name, int age, String email) {}
调用 new User("Alice", 30, "alice@example.com") 即可创建实例;user.name() 获取姓名;user.toString() 输出 User[name=Alice, age=30, email=alice@example.com]。
如何定制 Record 的行为
Record 允许在保持语义前提下适度扩展:
-
自定义构造器:可用于校验或默认值。需显式调用
this(...)委托给隐式构造器。例如:public record User(String name, int age, String email) {<br> public User {<br> if (name == null || name.trim().isEmpty())<br> throw new IllegalArgumentException("Name cannot be blank");<br> if (age }<br>} -
添加静态方法或静态字段:适合工厂方法或常量,如
public static final User ANONYMOUS = new User("Anonymous", 0, ""); -
添加实例方法:例如
public boolean isAdult() { return age >= 18; }。注意不能添加与组件同名的实例字段(会冲突)
Record 与传统 POJO/DTO 的关键区别
使用 Record 并不意味着完全替代普通类,需注意其约束:
-
不可继承:record 不能
extends其他类(也不能被继承),但可以实现接口。适合组合而非继承场景 - 无 setter:所有字段不可变,天然线程安全,适合做函数式编程中的值对象
-
不支持泛型类型推断构造器(如
new User<string>(...)</string>不合法),泛型需在 record 声明处定义:public record Pair<t u>(T first, U second) {}</t> -
序列化兼容性好:record 默认支持 Java 序列化(需实现
Serializable),且字段名即序列化字段名,与 JSON 库(如 Jackson)配合良好(通常无需额外注解)
实际使用建议
Record 最适合以下场景:
- API 接口层的请求/响应 DTO(如 Spring MVC 的
@RequestBody/@ResponseBody) - 数据库查询结果映射(配合 MyBatis 或 JPA 构造器注入)
- 函数间传递的中间数据结构(如 Stream 处理中的临时封装)
- 配置项、枚举替代方案(当选项含多个属性时,比 enum 更灵活)
避免用于需要频繁修改、有复杂生命周期管理或需深度继承体系的对象。若后续需求演变为需可变状态,应重构为普通类,而非强行扩展 record。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











