Java 14 中的记录特性
在 Java 14 中,记录(record)作为一种预览特性被引入。记录特性有助于创建不可变的数据对象。在 Java 15 版本中,记录类型得到了进一步的增强。在 Java 14 和 15 中,为了使用记录,需要传递一个标志 --enable-preview
。从 Java 16 开始,这个标志不再是必需的,因为记录已经成为 JDK 的标准部分。
Java 记录的目的
记录的主要目的是创建用于应用程序流程中的数据对象或 POJO(Plain Old Java Object)。在多层程序中,域/模型对象存储从数据源捕获的数据,然后这些模型对象被传递给应用程序/UI 层以处理数据,反之亦然,即 UI/应用程序将数据存储在数据对象中,然后将这些对象传递给数据层以填充数据源。
由于这些数据对象包含大量的字段,开发人员需要编写大量的 setter/getter 方法、参数化的构造函数、重写的 equals 方法和 hashcode 方法。在这种情况下,记录提供了一个大多数样板代码的解决方案,使得开发人员可以专注于所需的功能。
Java 记录的特性
以下是记录的一些特性,这使得记录成为一个令人兴奋的特性:
-
记录对象有一个隐式的构造函数,所有参数作为字段变量。
-
-
-
记录对象有一个隐式合理的实现
hashCode()
, equals()
, 和 toString()
方法。
-
在 Java 15 中,不能在记录中声明本地方法。
-
在 Java 15 中,记录的隐式字段不是
final
的,使用反射修改它们将抛出 IllegalAccessException
。
不使用 Java 记录的示例
让我们创建一个简单的程序,不使用记录创建一个 Student
对象并打印其详情。Student
有三个属性:id
、name
和 className
。为了创建一个学生对象,我们需要创建一个参数化的构造函数、setter 和 getter 方法、equals 和 hashcode 方法。这样我们的 Student
类大约有 60 行代码。
package com.tutorialspoint;
public class Tester {
public static void main(String args[]) {
Student student1 = new Student(1, "Mahesh", "XII");
Student student2 = new Student(2, "Sudhir", "XII");
System.out.println(student1);
System.out.println(student2);
boolean result = student1.equals(student2);
System.out.println(result);
result = student1.equals(student1);
System.out.println(result);
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 记录的示例
让我们重新使用记录创建上面的程序,创建一个 Student
对象并打印其详情。Student
有三个属性:id
、name
和 className
。在这里你可以看到差异,完整的 Student
类被一行代码作为 Student
记录所取代。
package com.tutorialspoint;
public class Tester {
public static void main(String args[]) {
Student student1 = new Student(1, "Mahesh", "XII");
Student student2 = new Student(2, "Sudhir", "XII");
System.out.println(student1);
System.out.println(student2);
boolean result = student1.equals(student2);
System.out.println(result);
result = student1.equals(student1);
System.out.println(result);
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 记录用于密封接口
由于记录默认是 final
的并且可以扩展接口。我们可以定义密封接口,并让记录实现它们以便更好地管理代码。
示例: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[]) {
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