> 文章列表 > Java 17 vs Java 8 (2) : record 关键字 详解 与 Lombok @Value 对比

Java 17 vs Java 8 (2) : record 关键字 详解 与 Lombok @Value 对比

Java 17 vs Java 8 (2) : record 关键字 详解  与 Lombok @Value 对比

JEP Link: https://openjdk.org/jeps/395

1. 基本用法介绍

Java record 关键字是 Java 14 中引入的一个新的语义特性,对于创建小型不可变对象非常有用。

	// record in Java 17public record PointRecord(int x, int y) {public int getRange() {return Math.abs(y - x);}}

在以上 Record 类中,定义了 x y 的 int 变量属性,并且定义了它的成员方法 getRange(),以上代码相当于:

	import java.util.Objects;class PointClass {private final int x;private final int y;PointClass(int x, int y) {this.x = x;this.y = y;}int x() {return x;}int y() {return y;}public boolean equals(Object o) {if (!(o instanceof PointClass other)) return false;return other.x == x && other.y == y;}public int hashCode() {return Objects.hash(x, y);}public String toString() {return String.format("Point[x=%d, y=%d]", x, y);}public int getRange() {return Math.abs(y - x);}}

用 record 关键字修饰的类相当于:

  • private final field(s) and coordinated public accessor method(s);
    提供以 private final 修饰的成员变量和对应的公共访问 get 方法;

  • a canonical constructor;
    全参的构造方法;

  • equals, hashCode, toString methods;
    提供 equals, hashCode, toString 方法

2. 与 Lombok @Value 使用场景对比

reference: https://www.baeldung.com/java-record-vs-lombok

Lombok 是一个 Java 库,可以将一些已知的模板代码自动生成为Java字节码,尽管它们都可以用来减少样板代码,但它们是不同的工具。因此,我们应该在给定的上下文中分析使用更适合我们需要的那个:

  • 共同点 - 常规用法,两种皆可

    record & Lombok @Value

	public record ColorRecord(int red, int green, int blue) {public String getHexString() {return String.format("#%02X%02X%02X", red, green, blue);}}
	@Valuepublic class ColorValueObject {int red;int green;int blue;public String getHexString() {return String.format("#%02X%02X%02X", red, green, blue);}}
  • 数据载体

    JEP 395: record 是作为不可变数据的载体的类,因此,record 会强制公开所有的成员字段。但是,Lombok @Value 允许我们自定义 getter 的名称、访问级别和返回类型,这点来看 @Value 使用体验更佳:

	@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);}}
  • 包含很多属性的类
	public record StudentRecord(String firstName, String lastName, Long studentId, String email, String phoneNumber, String address, String country, int age) {}

由于 record 关键字默认提供全参构造,所以当有些字段属性并不是必须时,初始化 record 类会在一定程度上影响代码可读性:

StudentRecord stu = new StudentRecord("John", "Doe", null, "john@doe.com", null, null, "England", 20);

而 Lombok 使用 @Builder 修饰能解决上述问题:

	@Getter@Builderpublic 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 stu = StudentBuilder.builder().firstName("John").lastName("Doe").email("john@doe.com").country("England").age(20).build();

综上,对于具有许多字段的对象,record 设计得并不是特别灵活,那么 Lombok @Builder确实是更好的选择。

  • 可变数据

    Java record 专门用于不可变数据,如果上下文需要一个可变的 Java 对象,可以使用 Lombok @Data:

	@Data@AllArgsConstructorpublic class ColorData {private int red;private int green;private int blue;public String getHexString() {return String.format("#%02X%02X%02X", red, green, blue);}}
  • 继承
    Java record 不支持继承。因此,它们不能被扩展或继承其他类。而 Lombok @Value 修饰的对象可以继承 final 类,此外,@Data 修饰的对象既可以扩展其他类,也可以被扩展。总之,如果类需要继承,应该使用 Lombok @Value:
	@Valuepublic class MonochromeColor extends ColorData {public MonochromeColor(int grayScale) {super(grayScale, grayScale, grayscale);}}

总结:Lombok 与 Java record 是不同的工具,服务于不同的目的。此外,Lombok 更加灵活,它可以用于 record 受限的场景。

以上,感谢浏览,如有不足请指正 😉