在 JDK 14 版本中,Java 引入了一项很酷的功能——记录类型(Records),一起看下它是什么,能帮我们做什么。
一、为什么需要记录类型(Records)
打个比方,我们要写一个类,这个类的任务就是存储一些简单的数据。
比如我们要存储一个人的信息,包括姓名、年龄和地址。我们可能会这样设计一个类:
public class Person {
private String name;
privateint age;
private String address;
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getAddress() {
return address;
}
@Override
public String toString() {
return"Person{name='" + name + "', age=" + age + ", address='" + address + "'}";
}
@Override
public boolean equals(Object o) {
if (this == o) returntrue;
if (o == null || getClass() != o.getClass()) returnfalse;
Person person = (Person) o;
return age == person.age && name.equals(person.name) && address.equals(person.address);
}
@Override
public int hashCode() {
return Objects.hash(name, age, address);
}
}
这个类看起来没什么问题,能存储数据并提供获取数据的方法。
但是,我们会发现,为了存储数据,我们需要写很多代码:
创建成员变量
写构造函数
提供 getter 方法
重写toString方法
重写equals和hashCode方法
这些方法大多数时候只是为了处理数据的存取、比较和输出。我们想要一个更简洁的方式来做这些事情。
这时,记录类型(Records)就来了!
二、记录类型是什么?
记录类型是Java 14引入的一种特殊类,用于简化数据存储类的编写。
它是一种新的数据结构,它是不可变的数据传输对象,类似于不可变的类。
使用记录类型,我们可以非常快速地定义一个类,它自动为我们提供了构造函数、getter 方法、toString、equals和hashCode方法。
我们只需要告诉Java我们需要哪些字段,其他的Java会自动为我们处理。
三、如何定义一个记录类型?
定义记录类型非常简单。我们只需要使用record关键字,后面跟着类名和字段列表。
例如:
public record Person(String name, int age, String address) {}
这段代码等价于上面我们写的Person类,但是它更简洁,且自动为我们生成了:
一个构造函数
三个字段的 getter 方法
toString方法
equals和hashCode方法
四、记录类型如何工作?
1.构造函数和字段
在普通的Java类中,我们需要手动写一个构造函数来初始化字段。而在记录类型中,字段和构造函数已经被自动生成了。
例如,下面这个普通类的构造函数:
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
在记录类型中,我们只需要声明字段即可,Java会自动为我们生成构造函数。
public record Person(String name, int age, String address) {}
2.Getter 方法
通常,我们还需要为每个字段编写 getter 方法:
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getAddress() {
return address;
}
在记录类型中,name()、age()和address()方法会自动生成,无需手动编写。
3.toString方法
toString方法用于返回对象的字符串表示。在普通类中,我们可能需要重写这个方法:
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + ", address='" + address + "'}";
}
而在记录类型中,toString方法会自动为我们生成,输出类似这样的字符串:
Person[name=John, age=30, address=Shanghai]
4.equals和hashCode方法
如果我们需要比较两个对象是否相等,或者把它们用作集合中的键,我们需要重写equals和hashCode方法。记录类型会自动为我们生成这两个方法。我们不需要手动实现它们。
五、记录类型的使用
JDK 14 引入的记录类型(Records)是一种新的数据结构,它是不可变的数据传输对象,类似于不可变的类。
记录类型提供了一种简洁的方式来创建具有明确字段和类型组合的数据类型。
被 record 修饰的 Person 对象的使用方式:
创建记录类型:
使用record关键字加上类型参数和字段初始化器来创建。
record Person(String name, int age, String address) {
// 记录类型实现的方法可以在这里定义
}
创建记录实例:
直接使用记录类型创建实例,字段值在创建时同时被初始化。
Person person = new Person("Alice", 25, "Wonderland");
访问字段:
通过点符号(.)访问记录的字段。
String name = person.name(); // 相当于 person.getName();
int age = person.age(); // 相当于 person.getAge();
方法重写:
虽然记录类型本身不提供方法,但我们可以在记录类型内部定义方法。
record Person(String name, int age, String address) {
public String getName() {
return name;
}
// 其他方法...
}
转换为旧式类:
可以将记录类型转换为旧的类类型,但反之则不行。
Person person = new Person("Bob", 30, "Builder Street");
Person personAsRecord = new Person.of(person.name(), person.age(), person.address());
被 record 修饰的 Person 对象不能使用的方式:
修改字段:
记录类型是不可变的,所以不能修改字段的值。
// 错误:不能修改字段值
person.name = "Charlie";
添加字段:
记录类型在创建时字段值就被初始化,不能添加新的字段。
// 错误:不能添加新的字段
person.gender = "Male";
删除字段:
记录类型是不可变的,所以不能删除字段。
// 错误:不能删除字段
delete person.age;
修改方法:
记录类型内部定义的方法不能被修改。
// 错误:不能修改方法
person.getName = () -> "New Name"; // 这不是一个有效的方法修改方式,实际中我们不能这样做
记录类型的设计目的是为了提供一种简单、类型安全且不可变的数据传输对象。它们非常适合用在需要快速创建轻量级数据类的场景中,尤其是在我们需要确保数据在传输过程中不会被修改时。
六、记录类型的好处
简洁
通过记录类型,我们只需要定义字段,Java会自动帮我们处理构造函数、getter 方法、toString、equals和hashCode,大大减少了代码量。
避免重复
记录类型为我们自动生成常用的代码,避免了我们手动编写相同的内容,比如toString、equals和hashCode方法。
更清晰的语义
使用记录类型声明的类通常用于存储数据,这让我们的代码语义更加清晰,其他开发者可以很容易理解这个类的作用。
不可变性
记录类型的字段默认是不可变的(即 final)。这意味着一旦创建,记录对象的字段就不能被修改。这对于存储数据类来说是非常合适的,因为我们通常希望数据一旦创建就不被更改。
七、记录类型的限制
不可继承
记录类型不能继承其他类(除非是java.lang.Record),因为它的设计就是为了简化数据存储,不能像普通类那样进行扩展。
不可修改
一旦创建,记录对象的字段就不能改变。这意味着它是不可变的,如果我们需要修改数据,必须创建一个新的对象。
最后总结
Java 14中的记录类型(Records)是一个非常实用的特性,帮助开发者简化了很多常见的代码。
通过记录类型,我们可以用更少的代码实现数据存储和管理,避免重复编写常用方法,提升代码的可读性和可维护性。
如果我们经常处理一些简单的数据对象,使用记录类型可以让我们的代码更简洁、更清晰。
record 这个关键字看起来真不错,可以少写很多代码,但也有一些局限,下次在使用 JDK17 的时候不妨用起来。
领取专属 10元无门槛券
私享最新 技术干货