Lombok学习实战
Lombok学习实战
Lombok 提供一组注解来代替 bean 类中的构造器、getter/setter、toString() 这样的样板代码,以减少 bean 类的代码冗余。如下是该项目官网中的介绍。
Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.
Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
有意思的是,类似于 Java / Jakarta 等名字的来源,Lombok 也是一个地名,而且也与印尼有关,它是印尼的一个小岛的名称。使用地名,尤其是岛屿名称作为项目或计算机语言名似乎已经形成了一种传统,可参考这篇 趣文。
如下地图中集齐了 Java, Jakarta 以及 Lombok。
使用Lombok
要使用 Lombok ,首先要引入该依赖。在 https://mvnrepository.com/
中搜索 lombok ,找到需要的版本的 lombok 页面 (如下以 1.18.24 为例) 。
1 | <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> |
若为 springboot 开发场景,由于 springboot 已经管理 Lombok。在 springboot-helloworld
的 pom.xml
文件中引入如下依赖。
1 | <dependency> |
接着在 idea 中搜索并安装 Lombok 插件并启用 (勾选)。
此时即可基于 Idea 使用 Lombok 。
主要注解一览
Lombok 主要注解。
注解 | 属性 | 描述 |
---|---|---|
@Getter |
AccessLevel |
作为字段注解时,生成该字段的 getter 作为类注解时,生成所有字段的 getter 对 static 修饰的字段无效对 final 修饰的字段有效 |
@Setter |
AccessLevel |
作为类注解时,生成所有字段的 setter 作为字段注解时,生成该字段的 setter 对 static 或 final 修饰的字段均无效 |
@ToString |
exclude of |
类注解。重写 toString() 。 |
@NoArgsConstructor |
类注解。生成无参构造器。 | |
@RequiredArgsConstructor |
类注解。生成带参构造器,参数为如下: 被 final 修饰的且未赋值的字段被 @NonNull 标注的字段 |
|
@AllArgsConstructor |
类注解。生成全参构造器。 | |
@EqualsAndHashCode |
exclude of |
类注解。重写 equals() / hashcode() 方法。 |
@Data |
类注解。如下注解的集合 @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode |
|
@NonNull |
作为参数注解时,不允许参数为 null ,若为 null 则抛出 NullPoiterException 作为字段注解时,不允许字段为 null |
|
@Log |
类注解。注入日志类 Logger 实例 (字段名 log ) 。 |
|
@Slf4j |
类注解。注入日志类 Slf4j 实例 (字段名 log ) 。 |
|
@Builder |
类注解。在其所标注的类中生成静态方法 build() 和内部建造者类,使得创建类对象时,参数可通过建造者模式写入。 |
|
@Cleanup |
局部变量注解。对于 InputStream , OutputStream 这样需要关闭资源的局部变量,自动生成 try-finally 代码。 |
|
val |
作用类似于 Java 10 推出的类型推导新特性 var 。 |
@Getter & @Setter
-
作为字段注解时,生成该字段的 getter / setter
-
作为类注解时,生成所有字段的 getter / setter
-
对 static 修饰的字段无效
-
对 final 修饰的字段,getter 有效而 setter 无效
字段注解
@Getter
作为字段注解时如下,User.java
中虽未写 getId()
方法,但在 Structure 中可看到存在该方法,且经过 Idea 反编译 .class
可以看出 .class
中已经存在了 getId()
方法。
@Setter
字段注解同理。
类注解
@Getter
作为字段注解时,生成所有字段的 Getter 方法,@Setter
同理。
特殊情况
-
对 static 修饰的字段无效。
-
对 final 修饰的字段,getter 有效而 setter 无效
注解属性
可以通过 value 属性设置 Getter / Setter 方法的可见性,如下。
- 字段注解优先于类注解。
AccessLevel.NONE
表示不创建对应方法。
@ToString
类注解,重写该类的 toString()
方法。
无 Getter 时。
有 Getter 时。
注解属性
of
可以通过 of 属性指定 toString()
方法输出的字段。指定多个时以 of = {"xx", "yy"}
形式书写。
exclude
可以通过 exclude 属性排除 toString()
方法输出的字段。指定多个时以 exclude = {"xx", "yy"}
形式书写。
@EqualsAndHashCode
类注解,重写该类的 equals()
和 hashCode()
方法。
无 Getter 时。
equals()
1 | public boolean equals(Object o) { |
canEqual()
1 | protected boolean canEqual(Object other) { |
hashCode()
1 | public int hashCode() { |
有 Getter 时。
equals()
1 | public boolean equals(Object o) { |
canEqual()
1 | protected boolean canEqual(Object other) { |
hashCode()
1 | public int hashCode() { |
注解属性
of
可以通过 of 属性指定 equals()
方法使用哪些字段完成判断,以及使用哪些字段用于 hashCode()
计算。指定多个时以 of = {"xx", "yy"}
形式书写。
exclude
可以通过 exclude 属性指定 equals()
方法不使用哪些字段完成判断,以及不使用使用哪些字段用于 hashCode()
计算。指定多个时以 exclude = {"xx", "yy"}
形式书写。
@NonNUll
-
作为参数注解时,该参数的值不允许为
null
-
作为字段注解时,该字段的值不允许为
null
参数注解
作为参数注解时,会在编译时加入判断是否为 null
的代码,若为 null
,则抛出 NPE 异常。
字段注解
作为字段注解时,会在该字段对应 Getter 中加入方法注解 @NonNull
,表示该方法不会返回 null
;同时在该字段对应的 Setter 的方法参数重加入参数注解 @NonNull
,表示若传入参数为 null
,则抛出 NPE 异常。
创建构造器的类注解
三个用于自动创建构造器的类注解。@NoArgsConstructor
, @RequiredArgsConstructor
, @AllArgsConstructor
。
@NoArgsConstructor
类注解,用于生成无参构造器。
当类中不显式写出构造器时 (即无有参构造器) ,默认有无参构造器。但当显式写出有参构造器时,默认无无参构造器,此时若需要无参构造器,可以为该类加上类注解 @NoArgsConstructor
。
@RequiredArgsConstructor
类注解。生成 (被要求的) 带参构造器,参数为如下:
- 被
final
修饰的 且未赋值 的字段 (一旦赋值,就不会作为带参构造器中的参数) - 被
@NonNull
标注的字段
当不存在所要求的参数时,不会创建带参构造器,但会创建无参构造器。
@AllArgsConstructor
类注解。生成带参构造器,参数为所有类字段 (不包括已经赋值的由 final
修饰实例字段,另外注意 static
修饰的字段不是实例字段)。
如下,如果 country
已赋值,则不会出现在带参构造器参数中。
@Data
@Data
注解是如下注解的组合。
@Getter
@Setter
@RequiredArgsConstructor
@ToString
@EqualsAndHashCode
@Builder
类注解。在其所标注的类中生成静态方法 build()
和内部建造者类,使得创建类对象时,参数可通过 建造者模式 写入。
如下,可以看到, @Builder
类注解做了如下处理。
- 创建了一个
UserBuilder
内部建造者类,其中以各字段名为名的建造方法均返回其自身 (UserBuilder
) 。 UserBuilder
内部建造者类可通过build()
方法返回User
对象。- 为
User
类创建了包可见的带参构造器。 - 为
User
类创建了类静态方法builder()
,返回UserBuilder
建造者类。
日志类注解
类注解。注入日志类实例 (字段名 log
) 。根据 官网 说明,Lombok 支持绝大多数流行的日志类,如 @CommonsLog
, @Flogger
, @JBossLog
, @Log
, @Log4j
, @Log4j2
, @Slf4j
, @XSlf4j
, @CustomLog
。他们的用法都是类似的。下面以 @Log
为例。
@Log
@Cleanup
局部变量注解。对于 InputStream
, OutputStream
这样需要关闭资源的局部变量,自动生成 try-finally 代码。
例如对于如下。
1 | package com.yukiyama.lombok; |
Idea 反编译后可看到实际上为如下。
1 | // |