在 Java 应用程序中,我们常常需要在应用程序的不同层之间,或者在不同服务之间传输数据。为此,我们使用 数据传输对象 (Data Transfer Objects, DTOs)。DTO 是一种简单对象,旨在保存数据,而不包含任何复杂的行为或逻辑。它的任务是将数据打包并传递到需要的地方。
现在,Java 在 Java 14 中引入了一个新特性,称为 Record。这些是特殊的类,专注于保存数据,就像 DTO 一样。最大的区别在于 Record 为我们做了很多重复的工作。例如,它们会自动生成获取数据的方法(比如 getter),并且会处理等值检查、toString() 等。这一特性在 Java 16 中完全可用,使 Record 成为一种现代、简洁的 Java 数据处理方式。
那么,为什么我们要比较 DTO 和 Record 呢?因为它们都用于相同的目的——携带数据。然而,随着 Java 的不断发展,了解何时使用哪一个非常重要。在本文中,我们将探讨它们之间的差异,并帮助你决定哪一个更适合你的需求,尤其是如果你正在开发现代 Java 应用程序。
一、什么是 DTO?
数据传输对象 (Data Transfer Object, DTO) 是一种简单的 Java 对象,用于在应用程序的不同部分之间传输数据。可以将其视为一个用于在应用程序各层之间携带数据的容器。例如,在一个 Web 应用程序中,DTO 可能用于从服务层向控制器传输数据,或者从控制器向视图层传输数据。
DTO 帮助保持应用程序各部分的分离,使代码更加有条理且易于维护。它们通常不包含任何业务逻辑或复杂行为。相反,它们只是保存数据。
二、DTO 是如何实现的?
DTO 通常作为普通的 Java 类实现。一个典型的 DTO 包括:
- 私有字段,用于保存它所持有的数据。
- Getter 和 Setter,用于访问和修改数据。
- 一个 构造函数,用于创建对象。
- 重写方法,如 toString()、hashCode() 和 equals(),以便以有意义的方式比较和打印对象。
以下是一个 UserDTO 类的示例:
import java.util.Objects;
public class UserDTO {
private String name;
private int age;
private String email;
// 构造函数
public UserDTO(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
// Getter 和 Setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
// 重写 toString 方法以获得有意义的输出
@Override
public String toString() {
return "UserDTO{" +
"name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
'}';
}
// 重写 equals 方法以比较对象
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserDTO userDTO = (UserDTO) o;
return age == userDTO.age && Objects.equals(name, userDTO.name) && Objects.equals(email, userDTO.email);
}
// 重写 hashCode 方法
@Override
public int hashCode() {
return Objects.hash(name, age, email);
}
}
这个 UserDTO 类保存了用户的信息:他们的名字、年龄和电子邮件。它还提供了基本功能,比如比较两个 UserDTO 对象(使用 equals())、生成唯一的哈希码(使用 hashCode())以及一个 toString() 方法,用于可读的输出。
使用像 Lombok 这样的工具,你可以避免手动编写样板代码,同时仍然拥有一个功能完备的 DTO。然而,正如我们稍后将探讨的,Java 提供了一种替代方案——Record,它也消除了大部分样板代码,但采用了不同的设计理念(默认不可变性)。
以下是如何使用 UserDTO:
public class UserDTOUsageExample {
public static void main(String[] args) {
UserDTO user = new UserDTO("xxx", 25, "xxx@example.com");
// 访问数据
System.out.println(user.getName());
System.out.println(user.getAge());
System.out.println(user.getEmail());
// 使用 toString() 方法
System.out.println(user);
// 比较记录
UserDTO anotherUser = new UserDTO("yyy", 22, "yyy@example.com");
System.out.println(user.equals(anotherUser));
}
}
接下来介绍什么是Java Record ...