跳转至

深入探索 Java 17 Record:简化数据类的强大工具

简介

在 Java 的发展历程中,创建简单的数据类(用于存储和传输数据)常常需要编写大量样板代码。Java 17 引入的 record 关键字,极大地简化了这一过程。record 为创建不可变的数据类提供了一种紧凑、简洁的语法,减少了开发人员编写重复代码的工作量,提升了代码的可读性和可维护性。本文将详细介绍 Java 17 record 的基础概念、使用方法、常见实践以及最佳实践,帮助读者更好地掌握这一强大的新特性。

目录

  1. Java 17 Record 基础概念
    • 什么是 Record
    • Record 与传统类的区别
  2. Java 17 Record 使用方法
    • 定义 Record
    • 创建 Record 实例
    • 访问 Record 字段
    • Record 的方法
  3. Java 17 Record 常见实践
    • 作为 DTO(数据传输对象)
    • 作为不可变数据结构
  4. Java 17 Record 最佳实践
    • 保持 Record 简单
    • 合理使用 Record 方法
    • 与其他特性结合使用
  5. 小结

Java 17 Record 基础概念

什么是 Record

Record 是 Java 17 引入的一种特殊类型,用于创建不可变的数据类。它本质上是一种语法糖,自动生成了构造函数、访问器方法(getter)、equals 方法、hashCode 方法以及 toString 方法,从而减少了开发人员编写样板代码的工作量。

Record 与传统类的区别

传统的 Java 类需要手动定义字段、构造函数、访问器方法、equals 方法、hashCode 方法以及 toString 方法。而 Record 会自动生成这些方法,使得代码更加简洁。例如,定义一个简单的传统 Java 类 Person

public class Person {
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass()!= o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && name.equals(person.name);
    }

    @Override
    public int hashCode() {
        return 31 * name.hashCode() + age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

使用 Record 定义相同功能的 Person

public record Person(String name, int age) {}

可以看到,使用 Record 定义的类更加简洁,代码量明显减少。

Java 17 Record 使用方法

定义 Record

定义一个 Record 非常简单,只需使用 record 关键字,后跟 Record 的名称和括号内的字段列表。字段可以是任何数据类型,包括基本类型、引用类型或其他自定义类型。例如:

public record Point(int x, int y) {}

创建 Record 实例

创建 Record 实例的方式与创建普通类实例类似,使用构造函数语法。Record 会自动生成一个与字段列表匹配的构造函数:

Point point = new Point(10, 20);

访问 Record 字段

Record 自动生成了访问器方法(getter),可以通过方法名直接访问字段。例如:

int x = point.x();
int y = point.y();

Record 的方法

除了访问器方法,Record 还自动生成了 equalshashCodetoString 方法。equals 方法用于比较两个 Record 实例是否相等,hashCode 方法用于生成实例的哈希码,toString 方法用于返回实例的字符串表示。例如:

Point point1 = new Point(10, 20);
Point point2 = new Point(10, 20);

System.out.println(point1.equals(point2)); // true
System.out.println(point1.hashCode() == point2.hashCode()); // true
System.out.println(point1); // Point[x=10, y=20]

Java 17 Record 常见实践

作为 DTO(数据传输对象)

在企业级应用开发中,DTO 常用于在不同层之间传输数据。Record 非常适合作为 DTO,因为它提供了不可变的数据结构,并且代码简洁。例如,定义一个用于用户登录的 DTO:

public record LoginRequest(String username, String password) {}

在服务层或控制器层,可以方便地使用该 DTO 来接收和处理用户登录请求:

public class LoginService {
    public boolean login(LoginRequest request) {
        String username = request.username();
        String password = request.password();
        // 处理登录逻辑
        return true;
    }
}

作为不可变数据结构

Record 创建的类是不可变的,这意味着一旦实例被创建,其字段的值不能被修改。这在多线程环境或需要保证数据一致性的场景中非常有用。例如,定义一个表示日期的不可变数据结构:

public record Date(int year, int month, int day) {}

在使用过程中,不用担心日期对象的值会被意外修改:

Date date = new Date(2023, 10, 5);
// 这里无法修改 date 的字段值

Java 17 Record 最佳实践

保持 Record 简单

Record 的设计初衷是为了创建简单的数据类,因此应尽量保持其字段数量适中,避免包含过多复杂的逻辑。如果需要添加额外的行为,建议将其放在单独的服务类或工具类中。

合理使用 Record 方法

虽然 Record 自动生成了许多方法,但在某些情况下,可能需要自定义这些方法。例如,如果 Record 中的字段包含复杂对象,可能需要重写 equalshashCode 方法以确保正确的比较和哈希计算。

与其他特性结合使用

Record 可以与 Java 的其他特性(如 Stream API、Lambda 表达式等)很好地结合使用。例如,在 Stream 操作中,可以方便地使用 Record 作为流中的元素:

import java.util.List;
import java.util.stream.Collectors;

public record Book(String title, String author) {}

public class Main {
    public static void main(String[] args) {
        List<Book> books = List.of(
                new Book("Java 核心技术", "Cay Horstmann"),
                new Book("Effective Java", "Joshua Bloch")
        );

        List<String> bookTitles = books.stream()
              .map(Book::title)
              .collect(Collectors.toList());

        System.out.println(bookTitles);
    }
}

小结

Java 17 Record 为开发人员提供了一种简洁、高效的方式来创建不可变的数据类。通过自动生成常用的方法,Record 减少了样板代码,提高了代码的可读性和可维护性。在实际开发中,合理使用 Record 可以提升开发效率,尤其是在创建 DTO 和不可变数据结构时。希望本文介绍的基础概念、使用方法、常见实践以及最佳实践能够帮助读者更好地理解和应用 Java 17 Record。