Java编程笔记31:Record
图源:Fotor懒设计
在日常使用的时候,我们往往需要创建一些“仅用于传输数据的类型”,比如Web编程时候的DTO。
将特殊用途的类型限制为“只读”的一个好处是,这些类型可以安全地在多线程之间共享,并且在涉及计算哈希值的时候,不用担心这些对象因为内部属性改变导致哈希值改变。
为什么要使用 Record
如果要创建一个“只读”类型,通常我们需要这样做:
public class Person1 {
private final String name;
private final Integer age;
public Person1(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person1 person1 = (Person1) o;
return Objects.equals(getName(), person1.getName()) && Objects.equals(getAge(), person1.getAge());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
}
@Override
public String toString() {
return "Person1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
}
我们需要做的是:
- 将属性设置为
private final
。 - 添加一个包含所有属性的构造器。
- 为属性添加Getter。
- 添加
hashCode
、equals
、toString
方法。
虽然大多数工作都可以借助IDE来完成,但是仍然需要话费一点时间在“样板代码”上,并且如果这个类型需要添加一些属性,我们还需要话费时间修改相应的代码。
在之前的文章中,我介绍了一个工具 Lombok,借助它我们可以改善此类的代码:
@Value
public class Person2 {
String name;
Integer age;
}
Lombok 可以帮助我们实现之前示例中的“样板代码”,我们只需要使用一个@Value
注解。
关于 Lombok 的更多介绍,可以阅读我的另一篇文章。
从 JDK14 开始,我们多了一种选项——使用Record
:
public record Person(String name, Integer age) {
}
看起来这里用
record
代替了class
,但实际上record
并不是一个关键字,只是一个包类型,这是官方出于某种向前兼容的考虑。
查看Person
对应的字节码:
public record Person(String name, Integer age) {
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String name() {
return this.name;
}
public Integer age() {
return this.age;
}
}
可以看到Person
在生成字节码后,由编译器生成了构造器和Getter。实际上相应的hashCode
、toStri