1. 概述

Java 14 引入了新的语义特性——记录(Records),它们非常适合创建小型不可变对象。另一方面,** lombok 是一个可以自动生成已知模式的 Java 库**,通过将代码转换为字节码来简化工作。尽管两者都能减少样板代码,但它们是不同的工具。因此,在特定上下文中,我们应该选择更适合的工具。

本文将探讨各种用例,包括 Java 记录的一些限制,并在每个示例中展示如何使用 lombok,以及与这两种解决方案的比较。

2. 小型不可变对象

Color 对象为例。一个 Color 由三个整数值组成,代表红、绿、蓝通道。此外,颜色还提供其十六进制表示,如 RGB(255,0,0) 的十六进制表示为 #FF0000。而且,我们希望具有相同 RGB 值的两种颜色被认为是相等的。

在这种情况下,选择使用 记录 是非常合适的:

public record ColorRecord(int red, int green, int blue) {
 
    public String getHexString() {
        return String.format("#%02X%02X%02X", red, green, blue);
    }
}

同样,lombok 也允许我们使用 @Value 注解创建不可变对象:

@Value
public class ColorValueObject {
    int red;
    int green;
    int blue;

    public String getHexString() {
        return String.format("#%02X%02X%02X", red, green, blue);
    }
}

然而,从 Java 14 开始,对于这些场景,记录将是自然的选择。

3. 透明的数据载体

根据 JDK 提案 (JEP 395),记录是充当不可变数据透明载体的类。因此,我们无法阻止记录暴露其成员字段。例如,之前例子中的 ColorRecord 不可能仅公开 hexString 并完全隐藏三个整数字段。

然而,lombok 允许我们自定义getter的名称、访问级别和返回类型。相应地更新 ColorValueObject

@Value
@Getter(AccessLevel.NONE)
public class ColorValueObject {
    int red;
    int green;
    int blue;

    public String getHexString() {
        return String.format("#%02X%02X%02X", red, green, blue);
    }
}

因此,如果需要不可变数据对象,记录是一个好的选择。

但如果想要隐藏成员字段,仅暴露使用它们执行的操作,lombok 更合适。

4. 包含许多字段的类

我们已经看到记录是如何方便地创建小型不可变对象的。现在来看看当数据模型需要更多字段时,记录会是什么样子。以 Student 数据模型为例:

public record StudentRecord(
  String firstName, 
  String lastName, 
  Long studentId, 
  String email, 
  String phoneNumber, 
  String address, 
  String country, 
  int age) {
}

我们可以预见到,创建 StudentRecord 将难以阅读和理解,尤其是当某些字段不是必需时:

StudentRecord john = new StudentRecord(
  "John", "Doe", null, "[email protected]", null, null, "England", 20);

为了简化这些场景,lombok 提供了 Builder 设计模式的实现。

要使用它,只需在类上添加 @Builder 注解:

@Getter
@Builder
public class StudentBuilder {
    private String firstName;
    private String lastName;
    private Long studentId;
    private String email;
    private String phoneNumber;
    private String address;
    private String country;
    private int age;
}

现在,我们可以使用 StudentBuilder 创建具有相同属性的对象:

StudentBuilder john = StudentBuilder.builder()
  .firstName("John")
  .lastName("Doe")
  .email("[email protected]")
  .country("England")
  .age(20)
  .build();

比较两者,我们可以看出使用 Builder 模式更可取,代码更清晰。

总的来说,记录更适合较小的对象。但对于包含许多字段的对象,缺少构造模式使得 lombok 的 @Builder 更合适。

5. 可变数据

我们可以只使用 Java 记录处理不可变数据。如果上下文需要可变的 Java 对象,我们可以使用 lombok 的 @Data 对象:

@Data
@AllArgsConstructor
public class ColorData {

    private int red;
    private int green;
    private int blue;

    public String getHexString() {
        return String.format("#%02X%02X%02X", red, green, blue);
    }

}

一些框架可能需要具有setter或默认构造函数的对象,如 Hibernate。创建 @Entity 时,我们将不得不使用 lombok 注解或纯 Java 代码。

6. 继承

Java 记录不支持继承。因此,它们不能被扩展或继承其他类。相反,lombok 的 @Value 对象可以继承其他类,但它们是最终的:

@Value
public class MonochromeColor extends ColorData {
    
    public MonochromeColor(int grayScale) {
        super(grayScale, grayScale, grayScale);
    }
}

此外,*@Data* 对象既可以继承其他类,也可以被继承。总结来说,如果需要继承,我们应该使用 lombok 的解决方案。

7. 总结

在这篇文章中,我们看到 lombok 和 Java 记录是不同的工具,适用于不同的目的。此外,我们发现 lombok 更具灵活性,可以在记录有限的场景中使用。

如往常一样,源代码可在 GitHub 上找到。