Lombok详解

2023-05-16

网上看到这篇文章,这里记录学习一下。

用🌶Lombok,让 Java 更简洁 - ENCODE the WORLD

零、 历史

        一个标准的 Java bean。一个典型的 Java bean 一般具有几个属性。每个属性具有一个 accessor 和 mutatorgetter 和 setter)。通常还会有一个 toString() 方法、一个 equals() 方法和一个 hashCode() 方法。初看上去,其中可预见的冗余就已经非常多了。如果每个属性都具有一个 getter 和 setter,并且通常如此。

一、 概述

Lombok是一个可以大幅减少java模板代码的工具

二、 使用

onX

Sup dawg, we heard you like annotations, so we put annotations in your annotations so you can annotate while you're annotating.

呦呵,我们听说你喜欢注解,所以我们将直接放入您的注解使得您可以在注解的时候注解你的方法。

  • JDK7 使用 onMethod=@__({@xxx})
  • JDK8 使用 onMethod_={@xxx}

这个方法是实验性的,因为不符合规范,仅仅用来解决不得不在其上加注释的问题。

val

使用位置
局部变量、ForEach

使用val可以作为局部变量和foreach循环的类型,它会执行类型推断,从初始化表达式推断出该变量的类型。

对于复合类型表达式如 bool ? new HashSet() : new ArrayList(), 结果又是 AbstractCollection 又是 Serializable, 推断的类型将是 AbstractCollection。因为它是类。
如果很模糊的话 如 null 则为 Object

var

非final本地变量的类型推断,在JEP286中建立了规范,它的工作原理与 val 完全相同,只是不是 final 的。

@NonNull

使用位置:
字段、方法、参数列表

该注解会在方法的顶部添加空指针检查。如果是空的话,抛出NullPointerException("param is marked @NonNull but is null");。在字段上使用时会生成一个包含该字段的构造器,它的get方法以及构造方法都会进行空指针检查。

会在方法的最顶部生成,如果是构造器,会在 super() 和 this() 之后生成检查方法。如果在方法的顶部已经有非空检查了,那么就不会创建。判断方法请查看官方文档。
@NonNull也有文档角色的概念,不再会产生警告,您可以将方法注解为@NonNull;这是允许的,不产生警告,也不生成任何代码。基本类型参数上的@NonNull会产生警告。不会生成空检查

可配置项

配置项默认值可用值描述
lombok.nonNull.exceptionTypeNullPointerException

NullPointerException

|IllegalArgumentException

|Assertion

指定IF中抛出的异常

@Cleanup

使用位置:局部变量

可填写的值类型默认值描述
valueStringclose关闭资源时需要调用的方法名称,该方法必须无参。

使用该注解以确保在代码执行路径退出当前范围之前自动清理给定资源,可注释在任何变量上

默认情况下会进行推断。有参的构造方法无法调用。

@Getter/@Setter

使用位置:类、字段

该注解会为标注的类、字段生成 get/set 方法,并且生成的方法名为驼峰命名法

刁钻的变量起名方式。。。

// 完蛋的起法

String name;

String naMe;

String nAME;

        可以通过指定访问级别 AccessLevel 来控制生成的 Getter 和 Setter 的访问权限。合法访问级别为PUBLICPROTECTEDPACKAGEPRIVATE。也可以使用None来禁用getter 和 setter 的生成。

       可以通过设置 onMethod=@__({@Annotations}) 和 onParam=@__({@AnnotationsHere}) 来规定注释在生成的方法上和字段上的注解。

对于以 is 开头且后面紧跟着大写字母的布尔字段,不会添加任何前缀来生成getter名称。@Getter 也可用于枚举。@Setter 不能用于枚举。

可配置项

配置项默认值可用值描述
lombok.accessors.chainfalsetrue|falsetrue,则生成的setter将返回 this(而不是 void)。 @Accessors 注解的显式配置的 chain 参数优先于此设置
lombok.accessors.fluentfalsetrue|false生成的getter和setter不会以bean标准 getis 或 set 为前缀,会和属性名一样
lombok.accessors.prefix+=/-=空列表字段前缀可以使用 += 添加前缀,或者使用 -= 删除前缀
lombok.getter.noIsPrefixfalsetrue|false为布尔字段生成的 getter 将使用 get 前缀而不是默认的 is 前缀,并且任何调用 getter 的生成代码, 如@ToString, 也将使用 get 而不是 is
lombok.copyableAnnotations空列表[完全限定类型列表]会将任何这些注解从字段复制到setter参数和getter方法。

@ToString

使用位置:类

       可以生成一个字符串:它会按顺序打印你的类名称以及每个字段,并以逗号分隔,默认情况会打印所有的非静态字段,也可通过配置来打印其他字段。

可填写的值类型默认值描述
includeFieldNamesbooleantrue在打印时包括每个字段的名称
@Exclude字段在字段上标注以排除这个字段
@Include字段、方法在字段上标注以包括这个字段,可以标记方法,使用方法的返回值参与计算
callSuperbooleanfalse在输出中包含父类的结果
doNotUseGettersbooleanfalse调用/不调用getters方法
onlyExplicitlyIncludedbooleanfalse仅有显示注释包含的才会输出
excludeString[]{""}这里列出的任何字段将不会被打印在生成的toString实现中。
ofString[]{""}如果存在,明确列出要打印的字段
  1. 如果有toString签名的方法,则不会生成额外的方法。
  2. 数组会通过 Arrays.deepToString 打印,如果包含自身,会导致栈溢出
  3. 在一个方法上同时加上 @ToString.Exclude 和 @ToString.Include, 这种情况会被排除
  4. 默认情况下,$ 开头的字段会被忽略,只能通过 @ToString.Include 手动包含
  5. 可用于枚举

可配置项

配置项默认值可用值描述
lombok.toString.includeFieldNamestruetrue|false设置为 false ,则lombok将省略该字段的名称,只需打印所有字段值的逗号分隔列表。如果明确指定,注解参数 includeFieldNames 优先于此设置。
lombok.toString.doNotUseGettersfalsetrue|false如果设置为 true,则在生成 toString 方法时,lombok 将直接访问字段,而不是使用getter(如果可用)。如果明确指定,注释参数 doNotUseGetters 优先于此设置。
lombok.toString.callSuperskip[ call | skip | warn ]1. call:会调用父类 toString
2. skip:不会调用父类
3. warnlombok会警告你

@EqualsAndHashCode

使用位置:类

可以使用字段为该类生成 Equals 和 HashCode 方法。

可填写的值类型默认值描述
callSuperbooleanfalse
@Exclude字段在字段上标注以排除这个字段
@Include字段、方法在字段上标注以包括这个字段,可以标记方法,使用方法的返回值参与计算
doNotUseGettersbooleanfalse调用/不调用getters方法
onParamAnyAnnotation[]{}规定注释在生成的方法上和字段上的注解
onlyExplicitlyIncludedbooleanfalse仅有显示注释包含的才会参与计算
excludeString[]{""}这里列出的任何字段将不会被包含
ofString[]{""}如果存在,明确列出要参与计算的字段
  1. 默认情况下,它将使用所有非静态,非瞬时的字段来计算
  2. 默认该注解不会使用超类的EqualsHashCode,可以通过 callSuper=true 来显式的调用超类的方法。可能会有某些自定义的 Equals 方法会造成意料外的效果,但是由 lombok 生成的 hashCode 和 equals 方法没有这个缺陷。所以推荐仅在子类无继承和 lombok 生成的方法上使用 callSuper
  3. TODO
  4. 数组会通过 Arrays.deepEquals 和 Arrays.deepHashCode 计算,所以包含自身的数组会导致栈溢出
  5. NaN = NaN
  6. 如果已经有 hashCode 和 equals 方法,则该注解无论如何都不会生效
  7. 如果方法标记为包含该字段的方法,则方法会覆盖字段。
  8. 默认情况下,$ 开头的字段会被忽略,只能通过 @EqualsAndHashCode.Include 手动包含

可配置项

配置项默认值可用值描述
lombok.toString.doNotUseGettersfalsetrue|false如果设置为 true,则在生成 equals和 hashCode 方法时,lombok 将直接访问字段,而不是使用getter(如果可用)。如果明确指定,注释参数 doNotUseGetters 优先于此设置。
lombok.equalsAndHashCode.callSuperwarn[ call | skip | warn ]1. call:会调用父类 toString
2. skip:不会调用父类
3. warnlombok会警告你

@XxxConstructor

使用位置:类

可以使用字段为该类生成各种各样的 Constructor

可填写的值类型默认值描述
staticNameString""静态工厂方法
onConstructorAnyAnnotation[]{}规定注释在生成的构造器上的注解
accessAccessLevellombok.AccessLevel.PUBLIC访问等级
@任意注解注解
  • staticName 生成的静态工厂方法拥有自动的类型推断,省去自己写反省的尴尬场景。使用该属性会使得构造方法变为私有的。

@NoArgsConstructor

为类生成无参的构造函数

可填写的值类型默认值描述
forcebooleanfalse使用 0 / false / null 初始化所有 final 字段
  1. 标记为 force=true 时约束字段不会生成任何检查
  2. 某些框架需要使用无参构造器,该注解主要用来配合 @Data 或其他生成构造器的注解使用。

@RequiredArgsConstructor

为每个需要特殊处理的字段生成一个带有对应参数的构造函数。

所有未初始化的 final 字段,以及未初始化的用 @NonNull 标记的字段,都会获得一个参数。对于标有 @NonNull 的字段,还会生成显式空检查

@AllArgsConstructor

为类中的每个字段生成对应参数的构造函数。标有 @NonNull 的字段会导致对这些参数进行空检查

可配置项

配置项默认值可用值描述
lombok.anyConstructor.addConstructorPropertiesfalsetrue | false如果设置为 true ,则 Lombok 将向生成的构造函数添加 @ java.beans.ConstructorProperties
lombok.[allArgsConstructor | requiredArgsConstructor | noArgsConstructor] .flagUsage未设置warning|error配置后,Lombok 将标记相关注解的任何用法为警告或错误
lombok.anyConstructor.flagUsage未设置warning|error配置后,Lombok 将标记所有构造器注解的任何用法为警告或错

注意

显示的构造函数不会阻止注解生成自己的构造函数。如果出现冲突,则会出现编译器错误

@Data

使用位置:类

大融合!将 @ToString@EqualsAndHashCode, 所有字段的 Getter, 所有非 final 字段的 @Setter 以及 @RequiredArgsConstructor !它通常用来生成简单的 POJO 和 Bean

可填写的值类型默认值描述
staticConstructorString""静态工厂方法,等价于 staticName
  • 无法使用 callSuper 等参数,如果需要使用,就需要显示的使用注解覆盖。
  • 所生成的 getter 和 setter 都是私有的,要覆盖需要再写
  • hashCode 与 equals 会跳过静态字段和 transient 字段。
  • 与 @RequiredConstructor 不同,任何构造函数都会阻止 @Data 生成构造函数。
  • 任何显式的 equals, getter, settertoString 方法都会阻止生成这些方法,对于 equals,不同类型的签名也不会生成。
配置项默认值可用值描述
lombok.data.flagUsage未设置warning|error配置后,Lombok 将标记所有构造器注解的任何用法为警告或错误

@Value

使用位置:类

@Data的不可变形式,相当于为属性添加final声明,只提供getter方法,而不提供setter方法

  • 等价于 final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter
  • 所有字段都是 private final 的
  • 可使用 @NonFinal 来去掉 final
  • 默认类本身也是 final 的
  • 生成一个覆盖每个参数的构造函数(除显式初始化的字段外)

@Builder

使用位置:类、方法、构造器

提供复杂的 builder APIs

可填写的值类型默认值描述
builderMethodNameString"builder"builder 方法的名称
buildMethodNameString"build"build 方法的名称
builderClassNameString""构造器的类名
toBuilderbooleanfalse生成一个在类中的 toBuilder 方法,返回包含当前类所有字段的 Builder
accessAccessLevelPUBLIC生成元素的访问级别
setterPrefixString""setter 的前缀名

@Builder 后的方法

  1. 一个名为 FooBuilder 的内部静态类,与静态方法(称为builder)具有相同的类型参数。
  2. 静态类中:一个non-static no-final字段对应目标的一个参数
  3. 静态类中:一个私有的不带参数的空构造函数
  4. 静态类中:外部类的每个参数会获得一个类型和字段名都相同的类似 setter 的方法,返回构造器本身以供链式处理
  5. 静态类中:一个 build 方法,调用外部的构造方法,传入每个参数。
  6. 静态类中:一个 toString 方法
  7. 外部类中:builder() 方法,返回构造器的实例

若上述内容已存在(只管方法名),则将跳过。

@Builder 后的类

效果类似于 @AllArgsConstructor(access = AccessLevel.PACKAGE)。如果有一个构造器,应该将 @Builder 放在构造器上

@Builder.Default

如果在 build 期间没有设置属性的任何值的化,它的值会为 0/null/false,可以在字段上添加 @Builder.Default 注释

@Builder.ObtainVia

使用位置:字段、参数

如果开启了 toBuilder 方法的生成,可以规定所属字段(参数)如何获取值,默认为通过 this.xxx 来获取

  • 指定字段获取值 this.value
  • 指定方法获取值 this.method()
  • 指定通过静态方法获取值 类.method(this)

@Singular

使用此注解可以注释一个集合字段(参数)

  1. 会生成两个方法:
    • 一个用于添加一个元素到集合中
    • 用于将另一集合中的所有元素添加到集合中。
  2. 生成 clearXxx 方法,用于清空集合。

拥有该注解后的构造器非常的复杂,以满足以下条件

  1. 调用 build() 时集合不可变
  2. build() 之后调用添加或删除方法不会修改生成的对象
  3. 生成的集合将被压缩

只能支持有限的类型,ListMap, Set 是其中较为典型的类型

如果注解不能单数化你的字段名,它将报错并要求你指定单数的名称

注意

  1. @Builder.Default 字段上的初始化程序将在编译过程中移动并存储在静态方法中,以确保在构建有值时不会执行该方法
  2. 可将 builderMethodName 配置为空字符串,这将阻止 builder() 方法的生成
  3. 上述特性可用于 toBuilder().build() 实现浅拷贝。

可配置项

配置项默认值可用值描述
lombok.data.flagUsage未设置warning|error配置后,Lombok 将标记所有构造器注解的任何用法为警告或错误
lombok.singular.useGuavafalsetrue|false是否使用 guava 的构造器实现 java.util 接口
lombok.singular.autotruetrue|false如果为 true ,lombok 会自动尝试通过假设它是一个常见的英语复数来单数化你的标识符名称。如果为 false ,则必须始终显式指定单数名称

@SneakyThrows

使用位置:方法、构造器

偷偷的抛出某些异常而不在方法上声明 throws,需要谨慎使用。实际上它时欺骗了编译器。原理是在 JVM 级别上,无论如何都可以抛出以常。

可填写的值类型默认值描述
valueClass<? extends Throwable>[]java.lang.Throwable.class偷偷抛出的方法名称

常见使用情况

  • 一个不必要的严格接口,Runnable 无论是否抛出异常,它都将被传递给 Thread
  • 一个不可能的异常,如:new String(SomeByteArray, "UTF-8") 声明其可抛出 UnsupportedEncodingException ,但是根据JVM规范,UTF-8必须始终可用。这里的 UnsupportedEncodingException 与使用String对象时的 ClassNotFoundError 差不多,你也没有必要捕获这些不可能的异常

注意

在被抛出后就不能捕获了,因为编译器不允许你为 try 体中没有方法声明抛出的异常类型编写对应的 catch 块

@Synchronized

使用位置:方法

是 synchronized 方法修饰符的更安全变体,与 synchronized 方法修饰符相似,只能用在静态方法上。 synchronized 锁定在 this 上,而注解锁定在 $LOCK 的静态字段。

可填写的值类型默认值描述
valueString""选择锁定的字段名

可以自行创建 $lock 或 $LOCK 字段。

本注解的作用是:锁定 this 和类对象可能会产生一些副作用,因为其他人也能锁定这些对象,这样可能会导致竞争和其他讨厌的线程错误。

注意

  • 自动生成的 $lock或 $LOCK 会使用 Object[]数组初始化字段,Lombok 这样做是因为 new Object() 不可序列化,但是大小为0的数组可以序列化,使用 @Synchronized 不会阻止对象序列化
  • 类中至少有一个 @Synchronized 方法意味着会有一个锁定字段,但是如果稍后删除所有这些方法,则不再有锁定字段。这意味着你预定的 serialVersionUID 会发生变化

@With

使用位置:字段、类

用于生成一个 withX(T newValue) 方法,该方法判断传入值和原有值是否相等,不相等会返回一个其他字段都相同的新对象。

比如说,为 final 字段设置 setter 是没有意义的,name,使用 @With 是很好的办法,

可填写的值类型默认值描述
valueAccessLevelfalse生成方法的访问类型
onMethodWith.AnyAnnotation[]{}在方法上生成的注解
onParamWith.AnyAnnotation[]{}在参数上生成的注解

注意事项

  • 该注解完全依赖构造方法克隆对象,所以要确保游泳构造方法
  • 静态字段无法生成方法,因为没有任何意义
  • 抽象类可用,会生成拥有适当签名的抽象方法
  • 会跳过所有 $ 开头的字段
  • 同名方法会覆盖

@Getter(lazy=true)

使用位置:字段

可以让 Lombok 生成一个 getter, 在第一次调用时会计算一次,之后缓存起来,如果计算该值需要占用大量 CPU,或者大量内存,则非常有用。

  1. 创建一个 private final 的变量
  2. 使用 @Getter(lazy=true) 注释字段

就算你的值为 null,也会被缓存,并且 Lombok 会为该方法加锁。

注意

  • 永远要使用 getter 访问字段,因为它是 AtomicReference 的,而且你无法分辨结果为 null 时到底为计算还是未计算。
  • 即使你使用 doNotUseGetters=true ,其他 Lombok 注释(如@ToString )也始终调用 getter

@Log

使用位置:类

它将为你生成一个 static final log = 你的类名 字段

注解类型对应 Log 类
@CommonsLogorg.apache.commons.logging.LogFactory.getLog(LogExample.class);
@Floggercom.google.common.flogger.FluentLogger.forEnclosingClass();
@JBossLogorg.jboss.logging.Logger.getLogger(LogExample.class);
@Logjava.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4jorg.apache.log4j.Logger.getLogger(LogExample.class);
@Log4j2org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4jorg.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4jorg.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
可填写的值类型默认值描述
topicString"" 代表当前类Logger 的主题/名称

可配置项

配置项默认值可用值描述
lombok.data.flagUsage未设置warning|error配置后,Lombok 将标记所有注解的任何用法为警告或错误
lombok.log.fieldNamelog其他名字生成的 logger 字段名称
lombok.log.fieldIsStatictruetrue| false生成的记录器logger是 static 字段。通过将此键设置为 false,生成的字段将是实例字段
lombok.log.xxxxxx.flagUsage未设置warning|error配置后,Lombok 将标记所有注解的任何用法为警告或错误

注意事项

  • 如果已存在名为 log 的字段,则将发出警告,并且不会生成任何代码。

experimental

实验字段们,可以正常使用,但没有主要功能那么强大的支持。以下的注解意味着

  • 没有经过完整测试
  • 不会像核心功能那样快速修复错误
  • 可能会发生变更
  • 可能会完全消失
  • 社区反馈积极的且看起来没有那么大破坏性,则可能会被接收为核心功能
注解作用当前状态
var本地变量,通过类型推断分配值
@Accessors支持三种模式
1. fluentgetter 和 setter 的方法都是属性名,并且 setter 返回当前对象
2. chain: setter 对象返回当前对象
3. prefix : 用于忽视指定前缀,如 字段中带 master_,则可忽略为本身字段名
中性
@ExtensionMethod可以包含一些方法到类中,使得其像实例方法一样使用。保持
@FieldDefaults通过该注解控制一些访问修饰符和访问级别积极
@Delegate将某些访问指定类、字段的调用重定向到该字段上消极
onX在最开始有所介绍不确定
@UtilityClass表示该类是工具类,不存在任何实例,自动为该类生成一个私有构造器并在被调用时抛出异常。将所有的成员都自动转换为 static积极
@Helper允许将方法放入方法,而不需要实例化内部类,直接调用未知
@FieldNameConstants为类生成一个包含所有字段字段名的静态内部类中性
@SuperBuilder为父类生成一个 builder
@Tolerate可在任何字段和方法标注,使Lombok忽略这些字段,例如本来Lombok 认为已经有并且不再生成的方法,可以让其忽略并生成
@JacksonizedJackson 准备的注解,自动配置生成的 Builder 用于 Jackson 的反序列化

三、Lombok配置

灵活的配置每个 Lombok 的配置项

  1. 可以在任何目录中创建。作用于该目录和其子目录
  2. lombok.config中配置项config.stopBubbling=true指明lombok的根目录为当前配置文件所在目录
  3. 配置文件是分层的,原则是接近源文件的配置设置优先
  4. 根目录的子目录中可以创建lombok.config配置文件,来覆盖根目录的配置文件
  5. 在配置文件的顶部,可以导入其他配置文件。import ../conf/aaa.config

四、DeLombok

        使用Delombok 命令把 Lombok 注解实现的类文件转换为不使用 Lombok 的 Java 源文件。如果是 src 整个目录,可以递归的实现转换,Delombok 会自动过滤非 Lombok 注解的文件进行原样拷贝。

        不仅可以了解到 Lombok 的实现内幕,还可以很好的做系统升级,比如要生成 javadoc 或者使用 Google Widget Toolkit 都是不支持 Lombok 的,这时候就可以使用 Delombok 进行反编译,同时也能解决我们使用 Lombok 升级 JDK 带来的不兼容问题。

五、Lombok深入

5.1 Lombok 是怎么实现的

       lombok是通过什么来实现在编译时的?通过 JSR 269: Pluggable Annotation Processing API(Java 规范提案)

       通过分析和置换抽象语法树所生成全新的字节码

   Javac 解析成抽象语法树之后(AST), Lombok 根据自己的注解处理器,动态的修改 AST,增加新的节点(所谓代码),最终通过分析和生成字节码。

5.2 Lombok 扩展

六、一些坏处

  1. 使用 Lombok 会强行使别人也需要安装 Lombok插件,否则到处报错,不过现在 IDEA 已经内置支持了 Lombok,如果我们定义的一个jar包中使用了Lombok,那么就要求所有依赖这个jar包的所有应用都必须安装插件,这种侵入性是很高的。
  2. 代码可读性,可调试性低
  3. 影响升级,Lombok对于代码有很强的侵入性,就可能带来一个比较大的问题,那就是会影响我们对JDK的升级。每次大升级都会使 一大票使用 Lombok 的发出哀嚎。
  4. Lombok自身的升级也会受到限制,而每个jar包可能又要依赖不同版本的Lombok,这就导致在应用中需要做版本仲裁,jar包版本仲裁是没那么容易的,而且发生问题的概率也很高。
  5. 破坏封装性,无脑使用 getter 和 setter 不如不使用。
  6. 而其个类如果有嵌套引用,不做特殊处理,序列化的时候会死循环。
  7. Lombok 违反了 Java annotation processor 的规定,使用 HACK 字节码的方式实现这些方法,可能会导致一些不好发现的问题,在多个 JVM 语言混用时容易出一些离奇的错误

七、拓展延伸

其于主流的代码生成工具

  1. AutoValue
    • 谷歌出品
    • 生成 Java源文件
  2. Immutables
    • 支持的特性较多
    • 提供了与AutoValue类似的功能,并添加了使用@value.modiizable生成可修改类的功能
对比项LombokAautoValueImmutables
LicenseMIT (also)Apache 2Apache 2
最低java版本1.61.61.7
生成的文件lombok修改了原class文件,加入生成的代码生成了另外一个java子类,不侵入原有的java代码,完全遵循java的规范,可以看到两个java文件和两个class文件生成了另外一个java子类,不侵入原有的java代码,完全遵循java的规范,可以看到两个java文件和两个class文件
生成类与模版类关系Enhanced generated class replaces template sourceGenerated source extends template sourceGenerated source extends template source
查看生成类使用delombok默认可见默认可见
使用方便性为类或字段添加注解即可加上注解的同时,需要按照一定的规范遍写代码加上注解的同时,需要按照一定的规范遍写代码
是否需要提前编译不用,加上注解后,就可以用其生成的方法编译一次,才能生效,编译前是找不到待生成的子类的编译一次,才能生效,编译前是找不到待生成的子类的
生成的代码是否可见不可见,实在要看需要反编译,不利于Debug可代码分析比如覆盖率等可以看见生成的源代码,在代码调试和分析时较方便可以看见生成的源代码,在代码调试和分析时较方便
不可变程度可以使用set方法修改类可以使用Immutability修改类强支持不可变

如何选择这三个工具

1)AutoValue和Immutables使用标准注释处理,Lombok使用非标准注释处理方法:

  • 开发者如果希望避免非标准依赖,那么应该使用AutoValue和Immutables;
  • 开发者不希望添加IDE插件或者其他非javac以及非基础Java IDE支持的第三方工具,那么建议使用AutoValue和Immutables;

2)Lombok修改了原class文件,生成的类与模版类在同一个包下,并且名字相同;AutoValue和Immutables生成的类继承自基础模版类,但是在同一个包下:

  • 开发者如果希望编译的class文件和源文件在同一个包下,并且同名,那么应该使用Lombok;
  • 开发者如果希望可以看到生成的代码,并且不希望影响原来的代码,那么应该使用AutoValue和immutebles;

3)三个工具都不同程度上的支持自定义,因此和这个需要根据实际需要进行选择:

  • Lombok提供了一个configuration system ,允许根据所需的约定调整生成代码。
  • Immutables提供了style customization,允许对生成的代码的多个点进行调整。
  • AutoValue允许用户通过一些方式User Guide,自行定义一些生成代码的规则。

4)从可变性看,三者的opinionated不同,AutoValue是不支持可变的,而Lombok和Immutables支持:

  • 希望类成为不可变类,使用AutoValue;
  • 希望类一定程度上支持可变,那么使用Lombk或者Immutables;

八、 参考文献

  1. 华山论剑之JAVA三大代码生成工具:Lombok、AutoValue和Immutables 2019.09.18 12:37:07
  2. Project Lombok 2021.04.19 00:00:00

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Lombok详解 的相关文章

  • lombok 中的@Data注解引起sonar的FindBugs问题

    实体类中增加 64 Data注解 xff0c 那样实体类在编译时就会自动生成getters and setters xff0c 虽然这么写可以使代码看起来更加的简洁 xff0c 但是会引起sonar的坏味道 xff0c 如果不涉及到代码的F
  • Eclipse适用lombok插件

    Eclipse适用lombok插件 1 下载 lombok jar 插件2 下载后放入Eclipse目录下3 打开cmd进入eclipse目录执行4 关闭弹出的警告窗口 xff0c 点击 Specify location 5 选择eclip
  • IDEA lombok包的@Data注解报错找不到符号

    问题描述 xff1a 工程编译报错 java 找不到符号 问题抽象 定位错误可以发现是getter setter的问题 由于采用了 64 Data注解 xff0c 所以优先考虑是lombok的问题 解决方案 首先排除以下可能 lombok插
  • Lombok 之 @RequiredArgsConstructor 注解

    概念 spring注入对象有三种方法 xff0c 属性注入 xff0c 构造器注入 xff0c setter注入 但是如果属性太多 xff0c 一个个写太麻烦 xff0c 所以lombok提供了一个注解 xff0c 使用 64 Requir
  • Lombok详解

    网上看到这篇文章 xff0c 这里记录学习一下 用 x1f336 Lombok xff0c 让 Java 更简洁 ENCODE the WORLD 零 历史 一个标准的 Java bean 一个典型的 Java bean 一般具有几个属性
  • 解决问题记录2:项目内使用lombok的@Log4j2失效

    问题描述 在使用Log4j2注解后 程序中使用log 启动加载时报错 找不到相对的依赖 检查lombok的依赖是正确的添加的 问题解决 尝试了网上的众多方法都没有解决 后想到是否是有其他的jar内做了lombok的依赖 导致依赖到了其他ja
  • idea 使用lombok @Slf4j ,找不到log,解决方案

    1 安装lombok插件 2 如果安装了lombok插件 但是编译的时候还是找不到log 检查Annotation Processors gt Enable annotation processing 是否勾选
  • Eclipse安装LomBok插件

    1 使用LomBok的好处在于实体类不用手动去生成set get方法了 类会在编译时自动生成 是代码简洁节省工作量 2 maven项目的pom文件添加坐标下载
  • 【进阶项目】Lombok 使用详解

    前言 在 Java 应用程序中存在许多重复相似的 生成之后几乎不对其做更改的代码 但是我们还不得不花费很多精力编写它们来满足 Java 的编译需求比如 在 Java 应用程序开发中 我们几乎要为所有 Bean 的成员变量添加 get set
  • Lombok @Wither/@With Inheritance(超/子类)

    请建议如何使用 Wither With当继承应用时 我有一个抽象类Parent和混凝土Child Child应该是不可变的 推杆 Wither两者都给了我两个错误 构造函数 Child String 未定义 Child 类型必须实现继承的抽
  • 如何使 Lombok + Gson 与 Spring AOP 代理一起工作

    假设有一个简单的类Student Data NoArgsConstructor AllArgsConstructor public class Student private Integer age private String name
  • IDEA 中的 Spring 支持与 Lombok:是否支持“导航到自动装配依赖项”?

    Lombok 支持生成构造函数 Inject注释 RequiredArgsConstructor onConstructor Inject 所以 而不是 Service public class FooService private fin
  • Spring Boot 3 与 Lombok

    将我的项目从 Spring Boot 2 7 升级到 3 0 后 我得到 找不到标志 由于 Lombok 生成的代码而导致编译器错误 有什么方法可以让它协同工作 Spring Boot 3 和 Lombok 注释 您应该更新到 lombok
  • Lombok/Jackson - 用于 json 数组的 POJO

    我有一个 json 数组 需要从服务器接收 反序列化 并将其发送 序列化 到另一台服务器 Example car name string parts engine wheels 我开始编写以下 POJO 来表示这个 Json 数组 impo
  • 如何使用 Lombok 在类构造函数中使用 @Lazy 注释?

    给定一个 AnimalService 类 public class AnimalService private DogService dogService private AnimalService Lazy DogService dogS
  • 如何在 eclipse luna 中配置 lombok

    我使用 Maven 在 eclipse Luna 中配置 lombok 注解已正确添加 但未生成 getter 和 setter eclipse ini vm E Program Files Java jdk1 7 0 60 bin vma
  • 在 Intellij 中查找 lombok 生成的构造函数的用法

    我有一个带有 lombok 注释的类 Value or Data 并且我正在寻找一种简单的方法来查找自动生成的构造函数的用法 我现在能做的就是找到构造函数的一种用法 将光标放在那里并运行 查找用法 命令 然后我得到我想要的结果 不过我想直接
  • annotationProcessor gradle 4.7+ 配置不运行 lombok

    我在使用 gradle 4 7 项目时收到以下消息 The following annotation processors were detected on the compile classpath lombok launch Annot
  • 绕过 Json jackson 和 lombok 构造函数要求

    使用 json 保存和加载数据需要 json 的构造函数来加载对象 并且我在使用 lombok 注释时遇到问题 我应该怎么办 这是我的类在尝试使用注释构建我的项目之前和之后的样子 Data public class Item before
  • 龙目岛与休眠

    这可能吗 没有看到太多关于它的讨论 当然 根据我的经验 它效果很好 这是一个示例实体 Entity Cache usage CacheConcurrencyStrategy READ WRITE public class PingerEnt

随机推荐

  • RabbitMQ(黑马spring cloud笔记)

    MQ 目录 MQ一 同步通讯和异步通讯1 同步通讯2 异步通讯 二 RabbitMQ1 部署2 架构3 常见消息模型3 1 基本消息队列 xff08 Basic Queue xff09 3 2 工作消息队列 xff08 Work Queue
  • Redis实战—黑马点评(一) 登录篇

    Redis实战 黑马点评 xff08 一 xff09 登录篇 来自黑马的redis课程的笔记 黑马程序员Redis入门到实战教程 xff0c 深度透析redis底层原理 43 redis分布式锁 43 企业解决方案 43 黑马点评实战项目
  • tigerVNC的简单使用教程(CentOS的远程桌面连接)

    tigerVNC的简单使用教程 xff08 CentOS的远程桌面连接 xff09 1 环境和软件准备 1 CentOS 6 3下 root 64 localhost rpm q tigervnc tigervnc server tiger
  • Redis实战—黑马点评(二)缓存篇

    Redis实战 黑马点评 xff08 二 xff09 缓存篇 目录 Redis实战 黑马点评 xff08 二 xff09 缓存篇1 什么是缓存1 1 缓存的作用和成本 2 添加 Redis 缓存3 缓存更新策略3 1 三种更新策略3 1 1
  • Reids实战—黑马点评(三)秒杀篇

    Reids实战 黑马点评 xff08 三 xff09 秒杀篇 来自黑马的redis课程的笔记 黑马程序员Redis入门到实战教程 xff0c 深度透析redis底层原理 43 redis分布式锁 43 企业解决方案 43 黑马点评实战项目
  • RT-Thread Stm32f103开启UART2(中断接收及轮询发送) 使用RT-Thread Studio

    RT Thread Stm32f103开启UART2 使用RT Thread Studio 1 使用RT Thread Studio新建RT Thread项目 2 修改dricer gt doard h 增加UART2的宏定义设置gpio接
  • 串口收发数据

    1 1 字符串接收函数 发送方结束标志是你接收方判断的依据 xff0c 也可以说是属于协议的一部分 我们这里使用串口助手数据发送自动添加了 r n xff0c 所以我们将它们看成结束标志 1 2 数据传输方式 计算机与外部进行沟通只有并行和
  • VsCode Studio的C/C++代码自动补全

    关于VsCode Studio的C C 43 43 代码自动补全 第一步 xff1a 需要下载VsCode中的C C 43 43 插件 如图 xff1a 插件下载后 xff0c 最好是重新启动一下VS 第二步 xff1a 找到设置 在输入框
  • Nginx lua设置Cookie,及学习Cookie

    网上看到这篇文章 xff0c 很喜欢这种分析思路 xff0c 这里学习记录一下 最近小了解了下cookie 以前觉得cookie无非就是一连串键值对 在深入了解之后发现 远没自己想的那么简单 自己果真太肤浅了 好吧 这里主要探讨一下以下几个
  • nginx中不同client设置User-Agent与user_agent的坑

    最近发现nginx内部用lua获取user agent xff0c 得到的是一个table值 xff0c 很奇怪 xff0c 自己测试记录一下 xff1a 1 nginx配置 location zcy hello set by lua re
  • Nginx - request_time和upstream_response_time详解

    网上查了查资料 xff0c 这里记录一下 前言 最近分析服务器性能 xff0c 考虑到nginx在前面做反向代理 xff0c 这里查一下nginx日志来反应服务器处理时间的问题 注 xff1a 本文提到的所有变量 xff0c 如果需要区分
  • Spring Boot 2.3.0 Redis拓扑动态感应,使用Lettuce拓扑刷新

    背景 关于 Redis 在生产中我们一般情况下都会选择 redis cluster 高可用架构部署 xff0c 既能保证数据分片并且实现节点的故障自动转移 基本部署拓扑如下 xff1a 创建测试集群 这里通过我封装的 pig4cloud r
  • Country Codes and Language Codes

    ISO 3166 Country Codes and ISO 639 Language Codes 1 ISO 3166 Country Codes Table 20 1 ISO 3166 Country Codes Country ISO
  • SIP 注册过程

    SIP协议包含两种类型的消息 xff0c 一种是请求行用于发出邀请 xff0c 而另一种则是状态行 xff0c 用于标明当前通信的状态 请求行和状态行军包含三部分 xff0c 其中每一部分以空格隔开 xff0c 不论是请求行还是状态行均以C
  • UUID原理,以及JAVA生成短8位UUID

    最近需要生成短uuid xff0c 网上查了查资料 xff0c 这里整理记录一下 xff0c 供大家参考 1 前言 UUID xff0c 全名叫做 Universally Unique Identifier xff0c 也就是通用唯一标识符
  • user agent查询(iPhone/ Android/ iPad/ Windows Phone/ Macintosh)

    这里分享一个查询user agent的网站 xff0c 里面可以搜索各个平台的user agent 1 网页 例如 xff1a iPhone的user agent https www plus a net tools user agent
  • 跨源资源共享(CORS)

    转自 https developer mozilla org zh CN docs Web HTTP CORS 跨源资源共享 CORS xff08 或通俗地译为跨域资源共享 xff09 是一种基于HTTP 头的机制 xff0c 该机制通过允
  • 工业软件CAD、CAE、CAM介绍

    最近看了一篇文章介绍工业软件CAD CAE CAM xff0c 这里记录分享一下 自从上世纪八十年代工业软件出现后 xff0c 设计师们终于不用通过手绘来完成图纸的设计了 xff0c 转而在电脑上完成 xff0c 设计效率极大提高 那么工业
  • 502 bad gateway原因、解决方法

    nbsp 网上查了查资料 这里记录一下 nbsp nbsp nbsp 在当今时代 每个人都使用互联网 通常 在使用 Internet 和访问网页时 计算机和网站之间可能会出现连接问题 这些连接问题会产生某些错误代码 称为 nbsp HTTP
  • Lombok详解

    网上看到这篇文章 xff0c 这里记录学习一下 用 x1f336 Lombok xff0c 让 Java 更简洁 ENCODE the WORLD 零 历史 一个标准的 Java bean 一个典型的 Java bean 一般具有几个属性