Java Record(记录类)

更新于 2025-12-27

Jakob Jenkov 2020-05-15

Java Record 是一种特殊类型的 Java 类,其语法简洁,用于定义仅包含数据且不可变的类。Java Record 实例非常适合用于保存从数据库查询、远程服务调用、CSV 文件等返回的数据记录。

Java Record 包含一个或多个数据字段,这些字段对应于普通 Java 类中的成员变量。Java 编译器会自动为这些字段生成 getter 方法、toString()hashCode()equals() 方法,因此你无需自己编写这些样板代码。由于 Java Record 是不可变的,因此不会生成 setter 方法。

Java Record 语法

Java Record 的语法非常简单。以下是一个表示“车辆”(Vehicle)的 Record 示例:

public record Vehicle(String brand, String licensePlate) {}

注意,这里使用的是 record 关键字而不是 classrecord 关键字告诉 Java 编译器这是一个 Record 类型。

此外,请注意该 Record 没有显式定义字段(field)。Record 的定义看起来像是一个普通的构造函数。实际上,这个“构造函数”就足以定义整个 Record。其中的两个参数(brandlicensePlate)告诉编译器:这个 Record 有两个字段 —— 每个构造参数对应一个字段。

Java 编译器会自动为这些字段生成:

  • 对应的私有字段(private final)
  • 公共的 getter 方法(方法名与字段名相同)
  • toString()hashCode()equals() 方法

使用 Java Record

你可以像使用其他 Java 类一样使用 Record —— 通过 new 关键字创建实例。以下是如何使用上面定义的 Vehicle Record 的示例:

public class RecordsExample {
    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle("Mercedes", "UX 1238 A95");
        System.out.println(vehicle.brand());
        System.out.println(vehicle.licensePlate());
        System.out.println(vehicle.toString());
    }
}

注意:编译器自动生成了 brand()licensePlate()toString() 方法。

上述代码的输出为:

Mercedes
UX 1238 A95
Vehicle[brand=Mercedes, licensePlate=UX 1238 A95]

Record 是 final 的

Record 类型是 final 的,这意味着你不能继承(子类化)一个 Record。换句话说,不能创建 Record 的子类(也不能有“子 Record”)。


多个构造函数

一个 Java Record 可以包含多个构造函数。以下是为 Vehicle Record 添加额外构造函数的示例:

public record Vehicle(String brand, String licensePlate) {
    public Vehicle(String brand) {
        this(brand, null);
    }
}

额外的构造函数必须写在 Record 的主体 {} 内部,并且必须调用主构造函数(canonical constructor)。这是 Java 编译器的要求,以确保所有字段都被正确初始化。

你可以根据需要添加任意数量的额外构造函数。


实例方法

你可以在 Record 中添加实例方法,就像在普通类中一样。例如,为 Vehicle Record 添加一个将品牌转为小写的方法:

public record Vehicle(String brand, String licensePlate) {
    public String brandAsLowerCase() {
        return brand().toLowerCase();
    }
}

注意:在方法内部,我们调用了自动生成的 brand() 方法。


静态方法

你也可以在 Record 中定义静态方法。例如:

public record Vehicle(String brand, String licensePlate) {
    public static String brandAsUpperCase(Vehicle vehicle) {
        return vehicle.brand().toUpperCase();
    }
}