Java 14 记录类

Java 14 引入了一种名为记录的类创建新方法,在本教程中,我们将学习:

  • 为什么我们需要Java记录
  • 如何创建记录并使用它
  • 重置和扩展记录类

推荐阅读: [Java 14 功能]( / 社区 / 教程 / Java-14 功能)

为什么我们需要Java记录?

Java 最常见的抱怨之一是它的词汇性. 如果你需要创建一个简单的 POJO 类,它需要以下的锅炉板代码。

  • 私人字段
  • Getter 和 Setter 方法
  • Constructors
  • hashCode(),等于(),和 toString() 方法

这种词汇性是对Kotlin(/社区/教程/kotlin)和Project Lombok(/社区/教程/java-project-lombok)的高兴趣的一个原因。

事实上,每次写这些通用方法的纯粹失望导致在Java IDEs中创建它们的捷径,如Eclipse和IntelliJ IDEA。

以下是显示 Eclipse IDE 选项的屏幕截图,以生成一类的仪式方法。

Eclipse Shortcuts Generate Ceremonial Methods

Java 记录旨在通过提供一个紧凑的结构来创建 POJO 类来消除这种词汇性。

如何创建Java记录

Java 记录是一个预览功能,它是在 JEP 359下开发的。

  1. JDK 14 已安装. 如果您正在使用 IDE,那么它必须为 Java 14 提供支持。Eclipse 和 IntelliJ 都已经为 Java 14 提供支持,所以我们在这里很好
  2. 启用预览功能:默认情况下,预览功能被禁用。

Java 14 Enable Preview Feature In Eclipse

您可以使用--enable-preview -source 14选项在命令行中启用 Java 14 预览功能。

假设我想创建一个员工模型类别,它将看起来像下面的代码。

 1package com.journaldev.java14;
 2
 3import java.util.Map;
 4
 5public class Employee {
 6
 7    private int id;
 8    private String name;
 9    private long salary;
10    private Map<String, String> addresses;
11
12    public Employee(int id, String name, long salary, Map<String, String> addresses) {
13    	super();
14    	this.id = id;
15    	this.name = name;
16    	this.salary = salary;
17    	this.addresses = addresses;
18    }
19
20    public int getId() {
21    	return id;
22    }
23
24    public String getName() {
25    	return name;
26    }
27
28    public long getSalary() {
29    	return salary;
30    }
31
32    public Map<String, String> getAddresses() {
33    	return addresses;
34    }
35
36    @Override
37    public int hashCode() {
38    	final int prime = 31;
39    	int result = 1;
40    	result = prime * result + ((addresses == null) ? 0 : addresses.hashCode());
41    	result = prime * result + id;
42    	result = prime * result + ((name == null) ? 0 : name.hashCode());
43    	result = prime * result + (int) (salary ^ (salary >>> 32));
44    	return result;
45    }
46
47    @Override
48    public boolean equals(Object obj) {
49    	if (this == obj)
50    		return true;
51    	if (obj == null)
52    		return false;
53    	if (getClass() != obj.getClass())
54    		return false;
55    	Employee other = (Employee) obj;
56    	if (addresses == null) {
57    		if (other.addresses != null)
58    			return false;
59    	} else if (!addresses.equals(other.addresses))
60    		return false;
61    	if (id != other.id)
62    		return false;
63    	if (name == null) {
64    		if (other.name != null)
65    			return false;
66    	} else if (!name.equals(other.name))
67    		return false;
68    	if (salary != other.salary)
69    		return false;
70    	return true;
71    }
72
73    @Override
74    public String toString() {
75    	return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + ", addresses=" + addresses + "]";
76    }
77
78}

Phew,这是70多行自动生成的代码,现在让我们看看如何创建一个员工记录类,这基本上提供了相同的功能。

1package com.journaldev.java14;
2
3import java.util.Map;
4
5public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
6}

哇,这不能比这更短了,我已经喜欢录音课了。

现在,让我们使用javap命令来弄清楚记录编译时幕后发生了什么。

 1# javac --enable-preview -source 14 EmpRecord.java
 2Note: EmpRecord.java uses preview language features.
 3Note: Recompile with -Xlint:preview for details.
 4
 5# javap EmpRecord      
 6Compiled from "EmpRecord.java"
 7public final class EmpRecord extends java.lang.Record {
 8  public EmpRecord(int, java.lang.String, long, java.util.Map<java.lang.String, java.lang.String>);
 9  public java.lang.String toString();
10  public final int hashCode();
11  public final boolean equals(java.lang.Object);
12  public int id();
13  public java.lang.String name();
14  public long salary();
15  public java.util.Map<java.lang.String, java.lang.String> addresses();
16}
17#

Java Record Class Details

如果您想要更多的内部细节,请使用 -v 选项运行 javap 命令。

1# javap -v EmpRecord

关于纪录班级的重要内容

  1. 记录类是最终的,所以我们不能扩展它
  2. 记录类 implicitly extend java.lang.Record class.
  3. 记录声明中指定的所有字段都是最终的.
  4. 记录字段是shallow不变的,并取决于类型。 例如,我们可以通过访问它来更改地址字段,然后对其进行更新
  5. 创建一个单一的构造器,包括记录定义中指定的所有字段
  6. 记录类自动为这些字段提供附加方法。 名称方法与字段名称相同,而不是像通用和常规方法
  7. 记录类提供

使用Java程序中的记录

让我们来看看我们使用 EmpRecord 类的一个简单的例子。

 1package com.journaldev.java14;
 2
 3public class RecordTest {
 4
 5    public static void main(String[] args) {
 6    	
 7    	EmpRecord empRecord1 = new EmpRecord(10, "Pankaj", 10000, null);
 8    	EmpRecord empRecord2 = new EmpRecord(10, "Pankaj", 10000, null);
 9
10    	// toString()
11    	System.out.println(empRecord1);
12    	
13    	// accessing fields
14    	System.out.println("Name: "+empRecord1.name()); 
15    	System.out.println("ID: "+empRecord1.id());
16    	
17    	// equals()
18    	System.out.println(empRecord1.equals(empRecord2));
19    	
20    	// hashCode()
21    	System.out.println(empRecord1 == empRecord2);		
22    }
23}

输出:

1EmpRecord[id=10, name=Pankaj, salary=10000, addresses=null]
2Name: Pankaj
3ID: 10
4true
5false

记录对象的工作方式与任何模型类、数据对象等相同。

扩展唱片制造商

有时,我们希望在我们的 constructor中进行一些验证或登录。例如,员工ID和工资不应该是负面的。 默认制造商不会有这种验证。 我们可以在记录类中创建一个紧凑型制造商。 该制造商的代码将被放置在自动生成的制造商的开始。

 1public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
 2    
 3    public EmpRecord {
 4    	if (id < 0)
 5    		throw new IllegalArgumentException("employee id can't be negative");
 6
 7    	if (salary < 0)
 8    		throw new IllegalArgumentException("employee salary can't be negative");
 9    }
10
11}

如果我们创建一个 EmpRecord 像以下代码:

1EmpRecord empRecord1 = new EmpRecord(-10, "Pankaj", 10000, null);

我们将获得 Runtime 例外,如:

1Exception in thread "main" java.lang.IllegalArgumentException: employee id can't be negative
2    at com.journaldev.java14.EmpRecord.<init>(EmpRecord.java:9)

记录类可以有方法吗?

是的,我们可以在记录中创建方法。

1public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
2
3    public int getAddressCount() {
4    	if (this.addresses != null)
5    		return this.addresses().size();
6    	else
7    		return 0;
8    }
9}

但是,记录是指数据载体,我们应该避免在记录类中使用实用方法,例如,上面的方法可以在实用类中创建。

如果您认为使用方法对于您的记录类是必不可少的,请仔细考虑是否真的需要记录类?

结论

Java 记录是对核心编程功能的欢迎补充,你可以将其视为一个命名。它旨在创建一个具有紧凑结构的数据载体对象,避免所有的锅炉板代码。

Published At
Categories with 技术
Tagged with
comments powered by Disqus