1. 简化代码
record
极大地简化了数据类的定义,避免了大量的样板代码。使用record
时,Java编译器会自动为你生成以下内容:
- 所有成员变量的
private final
字段 - 一个带有所有字段的全参构造器
- 所有字段的
getter
方法 equals()
、hashCode()
和toString()
方法
传统Java类定义
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
使用record
类定义
public record Person(String name, int age) {}
如你所见,使用record
仅需一行代码,编译器会为你生成与传统类相同的功能。
2. 不可变性
record
类是不可变的,所有字段默认是private final
。这意味着record
实例一旦创建,字段值就不能改变。这种不可变性提高了代码的安全性,特别是在多线程环境中。
3. 内置的equals()
、hashCode()
、toString()
方法
record
类自动生成equals()
、hashCode()
和toString()
方法,这些方法是基于所有字段的值生成的。这对于数据类的比较和调试非常有用,减少了手动编写这些方法的错误风险。
4. 简洁的构造器定义
record
类的构造器可以自动生成,省去了手动定义构造器的繁琐过程。你可以根据需要添加额外的逻辑到构造器中。
public record Person(String name, int age) {
public Person {
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
}
}
}
5. 默认的值语义
由于record
类主要用于数据传输,它们默认采用值语义。这使得它们在比较和集合操作中更有效。
6. 更好的模式匹配支持
record
类与Java的模式匹配特性(如switch
表达式和模式匹配instanceof
)紧密集成,提供了更简洁的语法和更强的类型检查能力。
7. 鼓励良好的设计实践
record
类设计的不可变性、值语义和自动生成的基本方法鼓励开发者采用更好的设计实践,减少潜在的错误和复杂性。
适用场景
- 数据传输对象(DTO):
record
类非常适合作为数据传输对象,用于在不同层次或服务之间传递数据。 - 值对象:
record
类也非常适合作为值对象,用于表达一个不可变的、无副作用的数据载体。
总结
1.使用record
类可以显著减少样板代码,增强代码的可读性和安全性,特别适合定义简单的、不可变的数据类。在需要快速定义数据结构的场景中,record
是一个非常方便且高效的选择。
2.record
类不会生成字段的setter
方法。
原因:
record
类的设计目的是用于定义不可变的数据类,因此它的所有字段都是private final
的。也就是说,record
类的实例一旦创建,它的字段值就不能再被修改,这正是record
类不可变性的核心特性之一。
当你定义一个record
时,编译器会自动为你生成以下内容:
- 私有的
final
字段,对应于你在record
头部定义的每个属性。 - 构造器,它接受所有的字段作为参数,并将这些参数的值赋给相应的字段。
getter
方法,对于每个字段生成一个对应的getter
方法。这些方法名称就是字段的名称(即不带get
前缀)。equals()
方法,用于比较两个record
对象的值是否相等。hashCode()
方法,用于生成基于字段值的哈希码。toString()
方法,用于生成包含字段值的字符串表示