Java中Record类型是Java 14中的预览函数引入的,并且应作为普通的 不可变 数据类,用于在类和应用程序之间进行数据传输。
像Enum
一样,Record也是一个特殊的类输入Java。类(Class)与记录(Record)之间的重要区别是,Record旨在消除设置和从实例获取数据所需的所有代码,Record将这种责任转移给生成编译器。
使用关键字record
在Java中创建此类Record类。就像在构造函数中所做的一样,需要在Record中提及属性及其类型。
在给定的示例中,EmployeeRecord
用于保存员工信息,即
package com.howtodoinjava.core.basic; public record EmployeeRecord(Long id, String firstName, String lastName, String email, int age) { }
要创建一条Record,请调用其构造函数并在其中传递所有字段信息。然后可以使用JVM生成的getter方法获取记录信息,并调用任何生成的方法。
package com.howtodoinjava.core.basic; public class RecordExample { public static void main(String[] args) { EmployeeRecord e1 = new EmployeeRecord (1l, "Lokesh", "Gupta", "howtodoinjava@gmail.com", 38); System.out.println(e1.id()); System.out.println(e1.email()); System.out.println(e1); } }
程序输出:
1 howtodoinjava@gmail.com EmployeeRecord[id=1, firstName=Lokesh, lastName=Gupta, email=howtodoinjava@gmail.com, age=38]
当无涯教程创建EmployeeRecord
时,编译器会创建字节码,并在生成的类文件中包含以下内容:
toString()
方法,用于打印Record中所有字段的状态/值。invokedynamic
的机制的equals()
和hashCode()
方法。id()
,firstName()
,lastName()
,email()
和age()
。java.lang.Record
,它是所有Record的基类。这意味着Record不能扩展其他类。final
,这意味着无法创建它的子类。如果在生成的类文件上运行javap
工具,将看到该类文件。
public final class com.howtodoinjava.core.basic.EmployeeRecord extends java.lang.Record { //1 public com.howtodoinjava.core.basic .EmployeeRecord(java.lang.Long, java.lang.String, java.lang.String, java.lang.String, int); //2 public java.lang.String toString(); //3 public final int hashCode(); public final boolean equals(java.lang.Object); //4 public java.lang.Long id(); public java.lang.String firstName(); public java.lang.String lastName(); public java.lang.String email(); public int age(); }
尽管所有Record都扩展了java.lang.Record
类,但是无涯教程仍然不能显式创建java.lang.Record
的子类。编译器不会通过。
final class Data extends Record { private final int unit; } // Compiler error : The type Data may not subclass Record explicitly
这意味着获取Record的唯一方法是显式声明一个Record并让javac
创建类文件。
无涯教程可以为Record的组件添加注释,这些注释适用于它们。例如,可以将@Transient
批注应用于id
字段。
public record EmployeeRecord( @Transient Long id, String firstName, String lastName, String email, int age) { // }
Record类的 serialVersionUID
是0L
,除非它是明确声明。
Record对象序列化的过程无法自定义,Record类定义的任何特定于类的代码 writeObject,readObject,readObjectNoData,readResolve,writeExternal和readExternal方法在序列化和反序列化期间都将被忽略。但是,writeReplace方法可用于返回要序列化的替代对象。
在执行任何 序列化或反序列化之前,无涯教程必须确保Record必须可序列化或可外部化。
import java.io.Serializable; public record EmployeeRecord ( Long id, String firstName, String lastName, String email, int age) implements Serializable { }
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class RecordExample { public static void main(String[] args) { EmployeeRecord e1 = new EmployeeRecord (1l, "Lokesh", "Gupta", "howtodoinjava@gmail.com", 38); writeToFile(e1, "employee1"); System.out.println(readFromFile("employee1")); } static void writeToFile(EmployeeRecord obj, String path) { try (ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream(path))){ oos.writeObject(obj); } catch (IOException e) { e.printStackTrace(); } } static EmployeeRecord readFromFile(String path) { EmployeeRecord result = null; try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path))){ result = (EmployeeRecord) ois.readObject(); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } return result; } }
程序输出:
EmployeeRecord[id=1, firstName=Lokesh, lastName=Gupta, email=howtodoinjava@gmail.com, age=38]
添加到Record中的新字段必须为Static 静态 也可以添加一种方法,该方法可以访问Record字段的内部状态。
编译器不会在隐式生成的字节码中使用添加的字段和方法,因此它们不属于任何方法实现,例如equals()
,hashCode()
或toString()
。
public record EmployeeRecord( Long id, String firstName, String lastName, String email, int age) implements Serializable { //additional field static boolean minor; //additional method public String fullName() { return firstName + " " + lastName; } }
可以添加构造器特定代码,以在紧凑的构造器中进行数据验证。
不需要为字段指定构造函数参数的分配,因为它以通常的方式在规范构造函数中发生。
public record EmployeeRecord( Long id, String firstName, String lastName, String email, int age) implements Serializable { public EmployeeRecord { if(age < 18) { throw new IllegalArgumentException( "You cannot hire a minor person as employee"); } } }
祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)
PPT设计进阶 · 从基础操作到高级创意 -〔李金宝(Bobbie)〕