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 关键字而不是 class。record 关键字告诉 Java 编译器这是一个 Record 类型。
此外,请注意该 Record 没有显式定义字段(field)。Record 的定义看起来像是一个普通的构造函数。实际上,这个“构造函数”就足以定义整个 Record。其中的两个参数(brand 和 licensePlate)告诉编译器:这个 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();
}
}