Java 17 引入了一个新的预览特性(Preview Feature):record
关键字。这个特性极大地简化了数据载体类(也常被称作值对象或数据传输对象DTO)的编写和阅读。传统的做法中,这些类通常由大量的私有字段和公共的 getter/setter 方法组成,这样的代码往往冗长且乏味。通过使用 record
关键字,Java 提供了一种更简洁、更易于理解和维护的方式来创建这样的类。
基本用法
一个 record
声明本质上是一个类声明的简化版本,它自动地、隐式地生成了:
- 所有的私有字段(从
record
的头部直接推导)。 - 一个构造函数,其参数与记录中声明的字段相对应。
- 每个字段的公共 getter 方法。
equals()
、hashCode()
和toString()
方法的实现,这些实现使用了字段的值。
示例:
public record Point(int x, int y) {
// 隐式构造函数、getter 方法、equals、hashCode 和 toString
// 可以定义额外的方法,但不能覆盖编译器生成的方法
// 示例:定义一个额外的方法计算点到原点的距离
public double distanceFromOrigin() {
return Math.sqrt(x * x + y * y);
}
}
// 使用
Point p = new Point(3, 4);
System.out.println(p.x()); // 访问 x 字段的值
System.out.println(p.distanceFromOrigin()); // 调用额外定义的方法
特性说明
- 不可变性:
record
类中的所有字段都是final
的,因此记录是不可变的。这有助于线程安全并鼓励在Java程序中使用不可变对象。 - 透明性:记录的内部表示对客户端代码是透明的,因为它们不允许访问任何内部字段(只能通过公开的 getter 方法)。
- 封装:尽管记录自动提供对字段的访问,但实际的字段实现是对外隐藏的,这提供了更好的封装。
- 类型安全:与使用 Map 或其他泛型集合相比,记录提供了类型安全的字段访问。
局限性和注意事项
- 不支持继承:
record
不能继承自其他类或实现接口(除了自动实现的equals
、hashCode
和toString
所需的java.lang.Object
)。 - 不允许自定义构造方法:除了由字段列表隐式定义的构造方法外,不能定义其他构造方法。
- 方法重写限制:
record
可以定义方法,但不能重写由编译器生成的equals
、hashCode
和toString
方法。 - 预览特性:
record
是Java 17中的一个预览特性,这意味着它在未来的版本中可能会更改或删除。要启用预览特性,需要在使用 Java 编译器和 JVM 时添加--enable-preview
标志。
总之,record
关键字为 Java 编程带来了一种更简洁、更现代的方式来处理数据载体类,尽管它目前还处于预览阶段,但它展示了 Java 在不断进化的道路上持续改进其语法和特性的承诺。