2020年3月发布的JDK 14引入了记录(预览语言特性),它为声明主要目的是保存数据的类提供了一种紧凑的语法。在记录中,所有低级的、重复的、容易出错的代码都像构造函数、访问器和utlity方法,如equals()
,hashCode()
,toString()
,都是根据记录的状态描述自动派生的。
前提条件
你需要启用预览功能的JDK 14:
记录声明
记录有一个名称和状态描述。状态描述声明了记录的组成部分和可选的主体:
record Owner(String name, String address, String city, String telephone) {}
record PetType(String name) {}
record Pet(LocalDate birthDate, PetType type, Owner owner) {}
复制代码
记录的表示方法是机械地、完全地从状态描述中衍生出来的,其成员如下:
- 一个
private
final
每个组件的字段 - 每个组件有一个
public
读取访问方法,其名称和类型与组件相同(例如:owner.name()
,owner.address()
)。 - 一个
public
构造函数 - 一个
equals()
的实现和hashCode()
toString()
的实现。
基本行为通过下面的测试来证明:
class Java14RecordTests {
@Test
void recordAccessors() {
var owner = new Owner("John Doe", "110 W. Liberty St.", "Madison", "6085551023");
assertThat(owner.name()).isEqualTo("John Doe");
assertThat(owner.address()).isEqualTo("110 W. Liberty St.");
assertThat(owner.city()).isEqualTo("Madison");
assertThat(owner.telephone()).isEqualTo("6085551023");
}
@Test
void recordEqualsAndHashCode() {
var pet1 = new Pet(
LocalDate.of(2019, 1, 1),
new PetType("dog"),
new Owner("John Doe", null, null, null)
);
var pet2 = new Pet(
LocalDate.of(2019, 1, 1),
new PetType("dog"),
new Owner("John Doe", null, null, null)
);
assertThat(pet1).isEqualTo(pet2);
assertThat(pet1.hashCode()).isEqualTo(pet2.hashCode());
}
@Test
void recordToString() {
var pet = new PetType("dog");
assertThat(pet.toString()).isEqualTo("PetType[name=dog]");
}
}
复制代码
限制条件
Record是一个受限制的类的形式,其限制是:
- 记录不能扩展任何其他类
- 任何其他被声明的字段必须是静态的
- 记录的组件是隐含的最终的。
其他行为
除了上述限制外,记录的行为与普通的类一样。
- 记录可以声明实例和静态方法、静态字段、静态初始化器:
record Owner(String name, String address, String city, String telephone) {
/* Static initializer */
static {
NONE = "N/A";
}
/* Static fields are allowed, both private and public */
private static String NONE;
/* Records may have static methods */
public static Owner anOwner(String name) {
return new Owner(name, NONE, NONE, NONE);
}
}
复制代码
- 记录可以声明构造函数,也可以声明紧凑构造函数。紧凑构造函数可以访问记录的组件:
record Pet(LocalDate birthDate, PetType type, Owner owner) {
/* `Compact` constructor */
public Pet {
requiresNotNull("birthDate", birthDate);
requiresNotNull("type", type);
requiresNotNull("owner", owner);
}
public Pet(LocalDate birthDate, PetType type) {
this(birthDate, type, null);
}
/* Records may have instance methods */
private void requiresNotNull(String name, Object obj) {
if (Objects.isNull(obj)) {
throw new IllegalArgumentException(name + " can't be null");
}
}
}
复制代码
- 记录可以覆盖所有的标准方法。
equals()
,hashCode()
。toString()
- 记录可以实现接口
- 记录可以被注解
...以及更多。
源代码
这篇文章的源代码可以在Github上找到:https://github.com/kolorobot/java9-and-beyond