一文了解Java中record和lombok的使用对比
作者:指北君 发布时间:2022-08-02 06:39:05
大家好,我是指北君。
Java的 record 关键字是Java 14中引入的一个新的语义特性。record 对于创建小型不可变的对象非常有用。另一方面,Lombok 是一个Java库,可以自动生成一些已知的模式为Java字节码。尽管它们都可以用来减少模板代码,但它们是不同的工具。因此,我们应该在特定情况下使用更适合我们需求的工具。
在这篇文章中,我们将探讨各种使用情况,包括java record 的一些限制。对于每个例子,我们将看到Lombok如何派上用场,并比较这两种解决方案。
小型不可变对象
我们的第一个例子,将使用Color
对象。一个Color
由三个整数值组成,分别代表红、绿、蓝三个通道。此外,一个颜色会暴露出它的十六进制表示。例如,RGB(255,0,0)
的颜色将有一个#FF0000
的十六进制表示。此外,如果两种颜色具有相同的RGB值,我们希望它们是相等的
。
由于这些原因,在这种情况下选择 record 是非常合理的。
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开始,record
将成为这些使用情况的最常见的方式。
透明的数据载体
根据JDK增强建议(JEP 395),record 是作为不可变数据的透明载体的类。例如,我们不能强迫前面例子中的ColorRecord
只暴露hexString
而完全隐藏三个整数字段。
然而,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);
????}
}
因此,如果我们需要不可变的数据对象,record 是一个很好的解决方案。
然而,如果我们想隐藏成员字段,只暴露使用它们进行的一些操作,Lombok会更适合。
有许多字段的类
我们已经看到了record 是如何以一种非常方便的方式来创建小型、不可变的对象的。让我们看看如果数据模型需要更多的字段,record 会是什么样子。在这个例子中,让我们考虑Student
的数据模型。
public?record?StudentRecord(
??String?name,?
??Long?studentId,?
??String?email,?
??String?phoneNumber,?
??String?address,?
??String?country,?
??int?age)?{
}
我们已经可以猜到,StudentRecord的实例化将很难阅读和理解,尤其是如果有些字段不是强制性的。
StudentRecord?john?=?new?StudentRecord(
??"John",?null,?"xxxx@qq.com",?null,?null,?"sh",?20);
为了方便这些使用,Lombok提供了一个[Builder设计模式](/creational-design-patterns#builder)的实现。
为了使用它,我们只需要用@Builder:
来注释我们的类。
@Getter
@Builder
public?class?StudentBuilder?{
????private?String?name;
????private?Long?studentId;
????private?String?email;
????private?String?phoneNumber;
????private?String?address;
????private?String?country;
????private?int?age;
}
现在,让我们使用StudentBuilder
来创建一个具有相同属性的对象。
StudentBuilder?john?=?StudentBuilder.builder()
??.name("John")
??.email("xxx@qq.com")
??.country("sh")
??.age(20)
??.build();
如果我们对两者进行比较,我们可以注意到,使用构建器模式是有利的,可以带来更干净的代码。
总而言之,record 对于较小的对象来说是更好的。虽然,对于有很多字段的对象来说,缺乏创建模式会使Lombok的@Builder
成为更好的选择。
可变数据
我们可以使用java record 专门处理不可变的数据。如果上下文需要一个可变的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);?
????????}
????}
一些框架可能需要带有设置器或默认构造函数的对象。例如,Hibernate就属于这种类型。当创建一个@Entity
时,我们必须使用Lombok的注解或纯Java。
继承性
Java record 不支持继承。因此,它们不能被扩展或继承其他类。另一方面,Lombok的@Value
对象可以扩展其他类,但它们是最终的。
@Value
public?class?MonochromeColor?extends?ColorData?{
????
????public?MonochromeColor(int?grayScale)?{
????????super(grayScale,?grayScale,?grayScale);
????}
}
此外,@Data
对象既可以扩展其他类,也可以被扩展。总之,如果我们需要继承,我们应该坚持使用Lombok的解决方案。
结论
在这篇文章中,我们已经看到Lombok和java records是不同的工具,有不同的用途。此外,我们发现Lombok更加灵活,它可以用于record 受到限制的场景。
来源:https://mp.weixin.qq.com/s/wfmfJb-HJaFs2sGU-NK8Jg


猜你喜欢
- 一、输入输出流对象cout:标准输出流cerr:标准出凑 和cout(只是用于如果是错误时要输出的)cin :&nb
- AsyncTask是Android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度
- 前言笔者上次用C#写.Net代码差不多还是10多年以前,由于当时Java已经颇具王者风范,Net几乎被打得溃不成军。因此当时笔者对于这个.N
- 创建一个简单的项目:<?xml version="1.0" encoding="UTF-8"?
- 用于字符串替换,你还在用以下的这种方法吗?String.format(String format, Object... args)这是Str
- LZ77压缩算法原理的理解数据压缩是一个减小数据存储空间的过程,目前被应用在软件工程的各个地方,了解其一些原理,方便我们更好的甄选压缩方案。
- 一、使用 System.Xml.Serialization类1、定义元数据引入System.Xml.Serialization命名空间。XM
- 一:背景1. 讲故事这几天都在修复bug真的太忙了,期间也遇到了一个挺有趣bug,和大家分享一下,这是一块sql挺复杂的报表相关业务,不知道
- start方法和run方法$start()$方法用来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到$cpu$时间片,就
- 我们开发WinFrom程序,很多时候都希望程序只有一个实例在运行,避免运行多个同样的程序,一是没有意义,二是容易出错。为了更便于使用,笔者整
- 前言Inotify会对工程内的所有文件夹设置”watch handle”。不幸的是,Linux默认的watch handle的限值不能满足实
- 前言又到了新的一月,今天提供一个Android自定义底部上拉布局的实现,起因是自己在项目中需要实现这样一个控件,干脆自己写一个练练手。写完了
- Java for循环打印菱形Java代码输出菱形的方法和思路有很多,在此分享一个稍带模块化拆分思想的解决方案,将需要输出的菱形拆分成8个模块
- 1. 为什么要使用线程池使用线程池通常由以下两个原因:频繁创建销毁线程需要消耗系统资源,使用线程池可以复用线程。使用线程池可以更容易管理线程
- [LeetCode] 2. Add Two Numbers 两个数字相加You are given two non-empty&n
- 奇怪的不等于(≠)最近,栈长用 IntelliJ IDEA 看源码时发现:咦~这是什么鬼?Java 不等于的写法不是一直都是 != 么?什么
- 一直做Android前端,今天突然心血来潮想搭建一个后台玩玩。平时都是需要什么样的接口直接出个接口文档扔给后台的兄弟,自己从来不操心他们内部
- 接上文Spring Cloud下基于OAUTH2认证授权的实现,我们将基于Spring Cloud实现OAUTH2的注销功能。1 增加自定义
- 前言了解一下将 Android library 发布到中央仓库(比如 Maven Center,jitpack) 的过程中关于一些细节的疑惑
- WebService是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Interne