Java 教程

Java 控制语句

面向对象编程

Java 内置类

Java 文件处理

Java 错误和异常

Java 多线程

Java 同步

Java 网络编程

Java 集合

Java 接口

Java 数据结构

Java 集合算法

高级 Java

Java 其他

Java APIs 和框架

Java 类引用

Java 有用资源

Java - 记录



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

Java 记录的目的

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

由于这些数据对象包含许多字段,开发人员需要编写许多 setter/getter 方法、参数化构造函数、重写的 equals 方法和 hashcode 方法。在这种情况下,record 派上用场,因为它提供了大部分样板代码,开发人员只需关注所需的功能。

Java 记录的特性

以下是使 record 成为一个令人兴奋的特性的一些特性:

  • Record 对象具有一个隐式构造函数,所有参数都作为字段变量
  • Record 对象对每个字段变量都有隐式的字段 getter 方法。
  • Record 对象对每个字段变量都有隐式的字段 setter 方法。
  • Record 对象具有隐式的、合理的 **hashCode()**、**equals()** 和 **toString()** 方法实现。
  • 在 Java 15 中,不能在记录中声明本地方法。
  • 在 Java 15 中,记录的隐式字段不是 final 的,使用反射修改会抛出 IllegalAccessException。

不使用 Java 记录的示例

让我们创建一个不使用 record 的简单程序,在这个程序中,我们创建了一个 Student 对象并打印其详细信息。Student 具有三个属性:id、name 和 className。为了创建一个学生,我们创建了一个参数化构造函数、setter、getter 方法、equals 和 hashcode 方法。因此,我们的 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

使用 Java 记录的示例

让我们使用 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 记录

由于记录默认情况下是最终的并且可以扩展接口,我们可以定义密封接口并让记录实现它们以更好地管理代码。

示例:密封接口的 Java 记录用法

考虑以下示例:

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

覆盖 Java 记录的方法

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

示例:覆盖 Java 记录方法

考虑以下示例:

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
广告