Java 简明教程

Java - Record

在 Java 14 中,引入了一个令人兴奋的功能 {} 作为预览功能。{} 功能有助于创建不可变数据对象。在 Java 15 版本中,{} 得到进一步增强。在 Java 14 和 15 中,为了使用 {},必须传递一个标志 --enable-preview。从 Java 16 开始,此标志不再需要,因为 {} 是 JDK 的标准部分。

Purpose of a Java Record

记录的主要目的是创建一个数据对象或 POJO,用于在应用程序流程中携带数据。在多层程序中,域/模型对象存储从数据源捕获的数据,然后将这些模型对象进一步传递到应用程序/UI 层以处理数据,反之亦然,其中 UI/应用程序将数据存储在数据对象中,然后将这些对象传递给数据层以填充数据。源。

由于这些数据对象包含许多字段,因此要求开发人员编写许多 setter/getter 方法、参数化 constructors、重写 equals 方法和 hashcode 方法。在这样的场景中,record 提供了帮助,因为它提供了大部分样板代码,而开发人员只需关注必需的功能。

Features of Java Record

以下是使记录成为令人兴奋的功能的记录功能:

  1. Record 对象有一个使用所有参数作为字段 variables 的隐式构造函数。

  2. Record 对象为每个字段变量有一个隐式字段读取器方法。

  3. Record 对象为每个字段变量有一个隐式字段设置器方法。

  4. Record 对象有一个 hashCode()equals()toString() 方法的隐式合理实现。

  5. 有了 Java 15,本地方法不能在记录中声明。

  6. 有了 Java 15,记录的隐式字段不是最终字段,并且使用反射进行修改将抛出 IllegalAccessException。

Example Without Using Java Record

让我们创建一个不使用记录的简单程序,其中我们要创建一个 Student 对象并打印其详细信息。该 Student 有三个属性:id、name 和 className。为了创建学生,我们创建了一个带参数的构造函数、设置器、访问器方法、equals 和散列码方法。因此,我们的 Student 类用近 60 多行代码就完成了。

package com.tutorialspoint;

public class Tester {
   public static void main(String args[]) {
      // create student objects
      Student student1 = new Student(1, "Mahesh", "XII");
      Student student2 = new Student(2, "Sudhir", "XII");

      // print the students
      System.out.println(student1);
      System.out.println(student2);

      // check if students are same
      boolean result = student1.equals(student2);
      System.out.println(result);

      // check if students are same
      result = student1.equals(student1);
      System.out.println(result);

      // get the hashcode
      System.out.println(student1.hashCode());
      System.out.println(student2.hashCode());
   }
}

class Student{
   private int id;
   private String name;
   private String className;

   Student(int id, String name, String className){
      this.id = id;
      this.name = name;
      this.className = className;
   }

   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getClassName() {
      return className;
   }
   public void setClassName(String className) {
      this.className = className;
   }

   @Override
   public String toString() {
      return "Student[id: " + id + ", name: " + name
         + ", class: " + className + "]";
   }

   @Override
   public boolean equals(Object obj) {
      if(obj == null || !(obj instanceof Student) ) {
         return false;
      }
      Student s = (Student)obj;

      return this.name.equals(s.name)
         && this.id == s.id
         && this.className.equals(s.className);
   }

   @Override
   public int hashCode() {
      int prime = 19;
      int result = 1;
      result = prime * result + ((name == null) ? 0 : name.hashCode());
      result = prime * result + ((className == null) ? 0 : className.hashCode());
      result = prime * result + id;
      return result;
   }
}

让我们编译并运行上述程序,这将生成以下结果 −

Student[id: 1, name: Mahesh, class: XII]
Student[id: 2, name: Sudhir, class: XII]
false
true
371251946
288252156

Example Using Java Record

让我们使用 record 重新创建上面的程序,其中我们将一个 Student 对象创建为 record 并打印其详细信息。该 Student 有三个属性:id、name 和 className。这里您可以看到区别,完整的 Student 类被一行代码替换为 Student record。

package com.tutorialspoint;

public class Tester {
   public static void main(String args[]) {
      // create student objects
      Student student1 = new Student(1, "Mahesh", "XII");
      Student student2 = new Student(2, "Sudhir", "XII");

      // print the students
      System.out.println(student1);
      System.out.println(student2);

      // check if students are same
      boolean result = student1.equals(student2);
      System.out.println(result);

      // check if students are same
      result = student1.equals(student1);
      System.out.println(result);

      // get the hashcode
      System.out.println(student1.hashCode());
      System.out.println(student2.hashCode());
   }
}

record Student(int id, String name, String className) {}

让我们编译并运行上述程序,这将生成以下结果 −

Student[id: 1, name: Mahesh, class: XII]
Student[id: 2, name: Sudhir, class: XII]
false
true
371251946
288252156

我们还可以向记录中添加自定义方法。但一般不需要。

Java Record for Sealed Interfaces

由于记录在默认情况下为最终记录,并且可以扩展 interfaces。我们可以定义 sealed interfaces,让记录实现它们以便更好地进行代码管理。

Example: Use of Java Record for Sealed Interfaces

考虑以下示例 −

package com.tutorialspoint;

public class Tester {
   public static void main(String[] args) {
      Person employee = new Employee(23, "Robert");
      System.out.println(employee.id());
	  System.out.println(employee.name());
   }
}
sealed interface Person permits Employee, Manager {
   int id();
   String name();
}
record Employee(int id, String name) implements Person {}
record Manager(int id, String name) implements Person {}

让我们编译并运行上述程序,这将生成以下结果 −

23
Robert

Overriding Methods of Java Records

我们可以轻松地覆盖记录方法实现并提供我们自己的实现。

Example: Override Java Record Methods

考虑以下示例 −

package com.tutorialspoint;

public class Tester {
   public static void main(String args[]) {
      // create student objects
      Student student = new Student(1, "Mahesh", "XII");

      System.out.println(student);
   }
}

record Student(int id, String name, String className) {
   public String toString() {
      return "Id: " + id + ", Name: " + name + ", class: " + className ;
   }
}

让我们编译并运行上述程序,这将生成以下结果 −

Id: 1, Name: Mahesh, class: XII