Java最高

通过。开始使用Spring 5和Spring Boot 2学习的春天课程:

>>查看课程

1.介绍

在许多Java应用程序中,在对象之间传递不可变数据是最常见但也最普通的任务之一。

在Java 14之前,这需要创建一个带有样板字段和方法的类,这些字段和方法容易出现小错误和混乱的意图。

随着Java 14的发布,我们现在可以使用记录来纠正这些问题。

在本教程中,我们来看看记录的基本原理,包括他们的目的,生成的方法和定制技术

2.目的

通常,我们编写类来保存数据,如数据库结果、查询结果或来自服务的信息。

在许多情况下,这些数据是不可变的,因为不变性了没有同步的数据有效性

为了实现这一点,我们用以下代码创建数据类:

  1. 私人,最后字段的每个数据块
  2. 每个字段的getter
  3. 公共构造函数,每个字段都有对应的参数
  4. =方法返回真正的当所有字段都匹配时,对于相同类的对象
  5. hashCode方法,当所有字段都匹配时返回相同的值
  6. toString方法,其中包括类的名称、每个字段的名称及其对应的值

例如,我们可以创建一个简单的数据类,带有一个名称和一个地址:

public class Person {private final String name;私有最终字符串地址;public Person(String name, String address) {this.name = name;this.address= address; } @Override public int hashCode() { return Objects.hash(name, address); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } else if (!(obj instanceof Person)) { return false; } else { Person other = (Person) obj; return Objects.equals(name, other.name) && Objects.equals(address, other.address); } } @Override public String toString() { return "Person [name=" + name + ", address=" + address + "]"; } // standard getters }

虽然这实现了我们的目标,但也存在两个问题:

  1. 有很多样板代码
  2. 我们模糊了类的用途——用名字和地址表示一个人

在第一种情况下,我们必须对每个数据类重复相同的冗长过程,单调地为每个数据块创建一个新字段,创建=,hashCode,toString方法,并创建接受每个字段的构造函数。

虽然ide可以自动生成许多这样的类,当我们添加一个新字段时,它们不能自动更新我们的类。例如,如果我们添加一个新字段,我们必须更新我们的=方法合并此字段。

在第二种情况下,额外的代码掩盖了我们的类只是一个数据类的事实有两个字符串字段:的名字地址

更好的方法是显式声明我们的类是一个数据类。

3.最基本的

在JDK 14中,我们可以用记录替换重复的数据类。记录是不可变的数据类,只需要字段的类型和名称。

=,hashCode,toString方法,以及私人,最后字段和公共构造函数,由Java编译器生成。

创建一个记录,我们用记录关键字:

public record Person (String name, String address) {}

3.1。构造函数

使用records,将为我们生成一个公共构造函数——每个字段都有一个参数。

在我们的情况下record的等效构造函数为:

public Person(String name, String address) {this.name = name;this.address= address; }

这个构造函数可以像类一样从记录中实例化对象:

Person Person = new Person("John Doe", "100 Linda Ln.");

3.2。getter

我们还免费接收公共getter方法——它们的名称与字段的名称匹配。

在我们的记录,这意味着a名称()地址()吸气剂:

@Test public void givenValidNameAndAddress_whenGetNameAndAddress_thenExpectedValuesReturned() {String name = "John Doe";String address = "100 Linda Ln.";Person Person =新人(姓名,地址);assertequal(名称、person.name ());assertequal(地址、person.address ());}

3.3。=

此外,一个=方法为我们生成。

该方法返回真正的如果提供的对象是相同的类型,并且它的所有字段的值都匹配:

@Test public void givenSameNameAndAddress_whenEquals_thenPersonsEqual() {String name = "John Doe";String address = "100 Linda Ln.";Person person1 =新人(姓名、地址);Person person2 =新人(姓名,地址);assertTrue (person1.equals (person2));}

如果两个字段之间有任何不同情况下,=方法将返回

3.4。hashCode

类似于我们的=方法,相应的hashCode方法也会为我们生成。

我们的hashCode方法返回两个相同的值对象,如果两个对象的所有字段值都匹配(排除由于生日悖论):

@Test public void givenSameNameAndAddress_whenHashCode_thenPersonsEqual() {String name = "John Doe";String address = "100 Linda Ln.";Person person1 =新人(姓名、地址);Person person2 =新人(姓名,地址);person2.hashCode assertequal (person1.hashCode () ());}

hashCode如果任何字段值不同,值也会不同。

3.5。toString

最后,我们还收到了一个toString方法生成一个字符串,该字符串包含记录的名称,后面紧跟着每个字段的名称及其方括号中的对应值

因此,实例化一个名字是“John Doe”地址为“100琳达Ln。结果如下toString结果:

Person[name=John Doe, address=100 Linda Ln.]

4.构造函数

虽然为我们生成了公共构造函数,但我们仍然可以自定义构造函数实现。

这种定制旨在用于验证,并且应该尽可能地保持简单。

例如,我们可以保证的名字地址提供给我们的记录不使用下面的构造函数实现:

public record Person(String name, String address) {public Person {Objects.requireNonNull(name);Objects.requireNonNull(地址);}}

我们也可以通过提供不同的实参列表来创建具有不同实参的新构造函数:

public Person(String name, String address) {public Person(String name) {this(name, "Unknown");}}

与类构造函数一样,属性可以引用字段关键字(例如,this.namethis.address),参数与字段的名称匹配(即,的名字地址)。

请注意,使用与生成的公共构造函数相同的参数创建构造函数是有效的,但这需要手动初始化每个字段:

public Person(String name, String address) {public Person(String name, String address) {this.name = name;this.address= address; } }

此外,声明无参数构造函数和参数列表与生成的构造函数匹配的构造函数将导致编译错误

因此,以下代码不能编译:

public record Person(String name, String address) {public Person {Objects.requireNonNull(name);Objects.requireNonNull(地址);} public Person(String name, String address) {this.name = name;this.address= address; } }

5.静态变量和方法

与常规Java类一样,我们还可以在记录中包含静态变量和方法

我们使用与类相同的语法声明静态变量:

public static String UNKNOWN_ADDRESS = "未知";}

同样,我们使用与类相同的语法声明静态方法:

public static Person(String name, String address) {return new Person("无名",address);}}

然后,我们可以使用记录的名称引用静态变量和静态方法:

的人。UNKNOWN_ADDRESS人。不愿透露姓名的(“100琳达Ln。”);

6.结论

在本文中,我们研究了记录在Java 14中引入的关键字,包括它们的基本概念和复杂性。

使用记录——以及它们的编译器生成的方法——我们可以减少样板代码并提高不可变类的可靠性。

可以找到本教程的代码和示例在GitHub

Java底部

通过。开始使用Spring 5和Spring Boot 2学习的春天课程:

>>查看课程
本文评论关闭!