- 记录 ( record) :是一种特殊形式的类,其状态 不可变,而且公共可读。
- 在 Java 语言规范中,一个 记录(Record) 的 实例字段 称为 组件 (component)。
- 记录(Record) 不能被继承。
- 记录(Record) 的 实例变量,默认是有 final 修饰 的。
- Java 16 中引入的 记录(Record) 是一种新的类类型,旨在简化 不可变数据模型的声明和使用。
一、记录 vs 普通类
1、代码对比
package org.rainlotus.materials.javabase.a04_oop.aboutrecord;
import java.math.BigDecimal;
public record Product(String id, String name, BigDecimal price) {
}
class Test{
public static void main(String[] args) {
var p = new Product("1234", "张三", new BigDecimal("12345.12"));
System.out.println(p.id() + "\t\t" + p.name() + "\t\t" + p.price());
}
}
public class Product {
private final String id;
private final String name;
private final BigDecimal price;
public Product(String id, String name, BigDecimal price) {
this.id = id;
this.name = name;
this.price = price;
}
public String id(){
return id;
}
public String name(){
return name;
}
public BigDecimal price(){
return price;
}
}
class Test{
public static void main(String[] args) {
var p = new Product("1234", "张三", new BigDecimal("12345.12"));
System.out.println(p.id() + "\t\t" + p.name() + "\t\t" + p.price());
}
}
2、小结
特性 | 记录(Record) | 普通类(Class) |
---|
不可变性 | 所有字段隐式 final | 需手动声明 final 字段 |
样板代码 | 自动生成方法(equals, hashCode等) | 需手动实现或依赖 IDE 生成 |
继承 | 不能继承其他类,但可实现接口 | 可继承其他类并实现接口 |
构造方法 | 自动生成全参构造方法 | 需显式定义构造方法 |
应用场景 | 不可变数据载体(DTO、值对象) | 通用业务逻辑、可变状态对象 |
二、记录(Record)的核心特性
1、不可变性(Immutability)
- 记录的所有字段(称为 组件)默认是 final 的,对象一旦创建后,其状态不可修改。
- 编译器自动生成基于所有组件的构造函数、访问器方法 等。
public record Response<T>(boolean success, T data) { }
Response<String> response = new Response<>(true, "操作成功");
public class ShoppingCart {
private List<Product> items = new ArrayList<>();
public void addItem(Product item) {
items.add(item);
}
public void removeItem(Product item) {
items.remove(item);
}
}
2、自动生成的方法
- 构造方法:根据组件生成全参构造方法。
- 访问器方法:为每个组件生成 public 访问器(如 name() 而非传统 getName())。
- equals() 和 hashCode():基于所有组件进行值比较。
- toString():返回包含所有组件名称和值的字符串。
3、限制
- 不能显式继承其他类(但可以实现接口)。
- 记录类是隐式 final 的,不可被继承。
- 组件必须是不可变字段(隐式 final)。
4、自定义行为
- 允许在记录中添加静态方法、实例方法、构造函数验证、类变量 等:
public record Person(String name, int age) {
public Person {
if (age < 0) throw new IllegalArgumentException("年龄不能为负数");
}
public String greet() {
return "Hello, " + name;
}
}

三、应用场景
1、数据传输对象(DTO)
- 用于在不同层(如数据库、服务层、前端)之间传输数据。
- 替代传统的 POJO,减少样板代码。
public record UserDTO(String username, String email, LocalDateTime createdAt) { }
2、值对象(Value Objects)
- 表示简单的不可变数据聚合,如坐标、金额、日期范围等。
public record Coordinate(double latitude, double longitude) { }
public record Money(BigDecimal amount, Currency currency) { }
3、模式匹配(Pattern Matching)
- 结合
<font style="color:#000000;">instanceof</font>
和 <font style="color:#000000;">switch</font>
表达式,简化数据解构。
Object obj = new Point(3, 4);
if (obj instanceof Point(int x, int y)) {
System.out.println("坐标: (" + x + ", " + y + ")");
}
4、临时数据容器
- 在流式操作(Stream API)中作为中间结果的载体。
List<Person> people = ...;
List<String> names = people.stream()
.map(p -> new NameRecord(p.firstName(), p.lastName()))
.filter(n -> n.lastName().startsWith("A"))
.map(n -> n.firstName() + " " + n.lastName())
.toList();
四、进阶用法
1、实现接口
public interface Shape {
double area();
}
public record Circle(double radius) implements Shape {
@Override
public double area() {
return Math.PI * radius * radius;
}
}
2、静态工厂方法
public record Email(String value) {
public static Email of(String input) {
if (!input.contains("@")) throw new IllegalArgumentException("Invalid email");
return new Email(input);
}
}
Email email = Email.of("user@example.com");
3、序列化支持
public record User(String id, String name) implements Serializable { }
User user = new User("123", "Alice");