1. Overview
1.概述
Java’s record keyword is a new semantic feature introduced in Java 14. Records are very useful for creating small immutable objects. On the other hand, Lombok is a Java library that can auto-generate some known patterns as Java byte-code. Even though both of them can be used to reduce the boilerplate code, they are different tools. Therefore, we should use the one that better suits our needs in a given context.
Java 的记录关键字是 Java 14 中引入的一个新的语义特性。记录对于创建小型不可变的对象非常有用。另一方面,Lombok是一个Java库,可以自动生成一些已知的模式作为Java字节码。尽管它们都可以用来减少模板代码,但它们是不同的工具。因此,我们应该在特定情况下使用更适合我们需求的工具。
In this article, we’ll explore various use-cases, including some limitations of the java records. For each example, we’ll see how Lombok can come in handy and compare the two solutions.
在这篇文章中,我们将探讨各种使用情况,包括java记录的一些限制。对于每个例子,我们将看到Lombok如何派上用场,并比较这两种解决方案。
2. Small Immutable Objects
2.小型不可变的物体
For our first example, we’ll use the Color object. A Color is composed of three integer values which represent the red, green, and blue channels. Furthermore, a color will expose its hex representation. For instance, the color with RGB(255,0,0) will have a hex representation of #FF0000. Besides, we want two colors to be equal if they have the same RGB values.
对于我们的第一个例子,我们将使用Color对象。一个颜色由三个整数值组成,分别代表红色、绿色和蓝色通道。此外,一个颜色会暴露出它的十六进制表示。例如,RGB(255,0,0)的颜色将有一个#FF0000的十六进制表示。此外,如果两种颜色有相同的RGB值,我们希望它们是平等的。
For these reasons, choosing a record would make perfect sense in this situation:
由于这些原因,在这种情况下,选择一个记录将是非常合理的。
public record ColorRecord(int red, int green, int blue) {
public String getHexString() {
return String.format("#%02X%02X%02X", red, green, blue);
}
}
Similarly, Lombok allows us to create immutable objects using the @Value annotation:
同样地,Lombok允许我们使用@Value注解来创建不可变的对象。
@Value
public class ColorValueObject {
int red;
int green;
int blue;
public String getHexString() {
return String.format("#%02X%02X%02X", red, green, blue);
}
}
Nevertheless, starting with Java 14, records will be the natural way for these use-cases.
然而,从Java 14开始,记录将成为这些使用情况的自然方式。
3. Transparent Data Carriers
3.透明的数据载体
As per JDK Enhancement Proposals (JEP 395), Records are classes that act as transparent carriers for immutable data. As a result, we cannot stop a record from exposing its member fields. For instance, we cannot force the ColorRecord from the previous example to only expose the hexString and completely hide the three integer fields.
根据 JDK 增强建议(JEP 395),记录是充当不可变数据的透明载体的类。因此,我们不能阻止一条记录公开其成员字段。例如,我们不能强迫前面例子中的ColorRecord只暴露hexString而完全隐藏三个整数字段。
However, Lombok allows us to customize the names, access levels, and return types of the getters. Let’s update the ColorValueObject accordingly:
然而,Lombok允许我们自定义名称、访问级别和获取器的返回类型。让我们相应地更新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);
}
}
Consequently, records are a good solution if we need immutable data objects.
因此,如果我们需要不可变的数据对象,记录是一个不错的解决方案。
However, if we want to hide the member fields and only expose some operations performed using them, Lombok will be better suited.
然而,如果我们想要隐藏成员字段,只公开使用它们进行的一些操作,Lombok将更适合。
4. Classes With Many Fields
4.有许多字段的类
We’ve seen how records represent a very convenient way of creating small, immutable objects. Let’s see how a record will look if the data model requires more fields. For this example, let’s consider the Student data model:
我们已经看到了记录是如何代表了一种非常方便的创建小型、不可改变的对象的方式。让我们看看如果数据模型需要更多的字段,记录会是什么样子。对于这个例子,让我们考虑Student数据模型。
public record StudentRecord(
String firstName,
String lastName,
Long studentId,
String email,
String phoneNumber,
String address,
String country,
int age) {
}
We can already guess that the instantiation of StudentRecord will be hard to read and understand, especially if some of the fields aren’t mandatory:
我们已经可以猜到,StudentRecord的实例化将很难阅读和理解,尤其是如果有些字段不是强制性的。
StudentRecord john = new StudentRecord(
"John", "Doe", null, "john@doe.com", null, null, "England", 20);
To facilitate these use-cases, Lombok provides an implementation of the Builder design pattern.
为了方便这些使用情况,Lombok提供了一个Builder设计模式的实现。
In order to use it, we simply need to annotate our class with @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;
}
Now, let’s use StudentBuilder to create an object with the same attributes:
现在,让我们使用StudentBuilder来创建一个具有相同属性的对象。
StudentBuilder john = StudentBuilder.builder()
.firstName("John")
.lastName("Doe")
.email("john@doe.com")
.country("England")
.age(20)
.build();
If we compare the two, we can notice that using the builder pattern is favorable, leading to cleaner code.
如果我们对两者进行比较,我们可以注意到,使用构建器模式是有利的,可以带来更干净的代码。
In conclusion, records are better for smaller objects. Though, for objects with many fields, the lack of creational patterns will make Lombok’s @Builder a better option.
总之,记录对于较小的对象来说是更好的。不过,对于有很多字段的对象来说,缺乏创建模式将使Lombok的@Builder成为更好的选择。
5. Mutable Data
5.可变数据
We can use java records exclusively for immutable data. If the context requires a mutable java object, we can use Lombok’s @Data object instead:
我们可以使用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);
}
}
Some frameworks may require objects with setters or a default constructor. For instance, Hibernate falls into this category. When creating an @Entity, we’ll have to use Lombok’s annotations or plain Java.
一些框架可能需要带有设置器或默认构造器的对象。例如,Hibernate就属于这个类别。当创建一个@Entity时,我们将不得不使用Lombok的注解或纯Java。
6. Inheritance
6.继承权
Java records do not support inheritance. Therefore, they cannot be extended or inherit other classes. On the other hand, Lombok’s @Value objects can extend other classes, but they are final:
Java记录不支持继承。因此,它们不能被扩展或继承其他类。另一方面,Lombok的@Value对象可以扩展其他类,但它们是最终的。
@Value
public class MonochromeColor extends ColorData {
public MonochromeColor(int grayScale) {
super(grayScale, grayScale, grayScale);
}
}
Besides, @Data objects can both extend other classes and be extended. In conclusion, if we need inheritance, we should stick to Lombok’s solutions.
此外,@Data对象既可以扩展其他类也可以被扩展。总之,如果我们需要继承,我们应该坚持使用Lombok的解决方案。
7. Conclusion
7.结语
In this article, we have seen that Lombok and java records are different tools and serve different purposes. Furthermore, we discovered that Lombok is more flexible, and it can be used for scenarios where records are limited.
在这篇文章中,我们已经看到Lombok和java记录是不同的工具,并且有不同的用途。此外,我们发现Lombok更加灵活,它可以用于记录受限的场景。
As always, the source code is available over on GitHub.
像往常一样,源代码可在GitHub上获得。