从 JDK 14 开始,Java 引入了 record
类型,用于简化 不可变数据对象(Immutable Data Object) 的书写。它类似于 Lombok 的 @Data
,但语义更明确:用于存放数据且不可修改。
1. 基本语法
package Works;
public record Student(String name, int age) {
}
record
会自动生成:- 构造方法
equals()
hashCode()
toString()
- 所有字段的 getter 方法(字段名本身就是方法名)
不会生成 setter 方法,因为 record 是不可变的。
2. 使用示例
package Works;
public class Main {
public static void main(String[] args) {
Student s = new Student("Warren", 18);
// record 自动生成 getter 方法
System.out.println(s.name()); // 输出: Warren
System.out.println(s.age()); // 输出: 18
// s.age = 20; // ❌ 编译错误,不能修改属性值
}
}
3. record 的不可变性
- record 的字段都是
final
修饰的,表示引用不可变。 - 注意:不可变是浅层的,引用对象的内部内容仍然可以修改。例如:
public record Classroom(String name, int[] scores) {}
public class Main {
public static void main(String[] args) {
int[] arr = {90, 95, 100};
Classroom c = new Classroom("Class A", arr);
// 修改数组内容
c.scores()[0] = 50;
System.out.println(Arrays.toString(c.scores())); // [50, 95, 100]
}
}
⚠ record 保证引用不可变,但不能保证引用对象本身不可变。如果需要深度不可变,需要自己做防御性拷贝(deep copy)。
4. record 的特点总结
特性 | 说明 |
---|---|
自动生成构造方法 | 简化代码,无需手写 |
自动生成 equals() 、hashCode() 、toString() |
可直接用于比较、打印 |
只生成 getter | 没有 setter,属性不可直接修改 |
final 字段 |
引用不可变,但引用对象内容可能可变 |
用途 | 存放不可变数据、DTO、返回值对象等 |
5. record vs 普通类 + Lombok
- 普通类 + Lombok 可以生成 getter/setter,但语义不明确,需要手动控制不可变性。
- record 自带不可变语义,更安全,更适合 只存储数据、没有业务逻辑的对象。