The article was initially published at carloschac.in
🏁 Records 💾
记录是Java语言中一种新型的类型声明。 像一个枚举, 一种记录 is a restricted form of class. It declares its representation and commits to an API that matches that representation. 记录s give up a freedom that classes usually enjoy: the ability to decouple API from representation. In return, 记录s gain a significant degree of concision.
记录具有名称和状态描述。 状态描述声明记录的组成部分。 (可选)记录具有正文。 例如:
record Point(int x, int y) { }
Let's get started
⬇️ Download OpenJDK 14.0.1
🚥 Set the JAVA_HOME to point to the downloaded JDK 14
$ export JAVA_HOME=/path/to/jdk14
$ export PATH=$JAVA_HOME/bin:$PATH
🚀 Writing our first Java Record 💾
public record Person(
String firstName,
String lastName,
String address,
LocalDate birthday,
List<String> achievements) {
}
💻 Compile it with javac
$ javac --enable-preview -source 14 Person.java
💻 Compile it with maven
为您的编译器插件添加以下配置pom.xml
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>14</release>
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin>
$ mvn compile
🚧 What's generated by the compiler?
$ javap -p Person.class
public final class Person extends java.lang.Record {
private final java.lang.String firstName;
private final java.lang.String lastName;
private final java.lang.String address;
private final java.time.LocalDate birthday;
private final java.util.List<java.lang.String> achievements;
public Person(java.lang.String, java.lang.String, java.lang.String, java.time.LocalDate, java.util.List<java.lang.String>);
public java.lang.String toString();
public final int hashCode();
public final boolean equals(java.lang.Object);
public java.lang.String firstName();
public java.lang.String lastName();
public java.lang.String address();
public java.time.LocalDate birthday();
public java.util.List<java.lang.String> achievements();
}
因为记录在语义上声称是其数据的简单,透明持有者,所以记录会自动获取许多标准成员:
- 状态描述每个组成部分的私有最终字段;状态描述的每个元素的公共读取访问器方法,具有与组件相同的名称和类型;一个公共构造函数,其签名与状态描述相同,该构造函数根据相应的参数初始化每个字段;equals和hashCode的实现,如果两个记录属于相同的类型并且包含相同的状态,则表示两个记录相等。 和toString的实现,其中包括所有记录组件的字符串表示形式及其名称。
⚠️ Shallowly Immutable Data
Similarly to the tests that we did in the article Immutables/AutoValue/Lombok Which One? where we check the default behavior in terms of immutability for those libraries, with the below test we demonstrate the statement mentioned in the JEP 359: Records:
记录提供了用于声明类的紧凑语法,这些类是透明的持有人浅不变的数据。
📐 Test Immutability
@Test
void immutability() {
// Create a mutable list with 1 element
var achievements1 = new ArrayList<String>();
achievements1.add("Speaker");
achievements1.add("Blogger");
var achievements2 = List.of("Speaker", "Blogger");
// Create person 1, assigning the list1
var person1 = new Person(
"John",
"Doe",
"USA",
LocalDate.of(1990, 11, 11),
achievements1
);
// Create person 2, assigning the list2
var person2 = new Person(
"John",
"Doe",
"USA",
LocalDate.of(1990, 11, 11),
achievements2
);
// Compare the 2 objects
// Test passes since the fields contain the same values
assertThat(person1).isEqualTo(person2);
// Mutate the list used on Model 1
achievements1.add("AnotherValue");
// Compare the 2 objects:
// - PASSES objects are NOT EQUAL for Records 😮 🔴
assertThat(person1).isNotEqualTo(person2);
}
当使用签名中具有可变数据类型的记录或数据类型是接口时,有两种方法可以确保不变性,并且我们不确定实现方式,即java.util.Date要么java.util.List
1)在记录的构造函数中创建数据类型的安全副本。 2)创建记录时仅传递不可变的对象。
🔆 Conclusions
- ✅记录可以将多行代码简化为一个代码行。✅With JDK 14, we can prescind of using some code generation libraries to minimize boilerplate code.✅A great option for:🔝树节点🔝DTO🔝复合地图键🔝留言🔝价值包装🔝歧视实体⚠️记录只是浅层不可变,这意味着如果我们要保证不变性,就必须考虑传递给它们的数据类型。⚠️记录是预览语言功能,在JDK中还不是标准。
相关文章: