lombok 实战

其实早就听过lombok,作为java开发者心中奇技淫巧,确实给我们开发带来了很多便捷。很多大牛也写博客对其进行详细的介绍,文章末尾会给出一些文章链接以供学习,而本篇文章记录下本人在接触、使用lombok后的一些心得。

lombok 介绍

作为一个java开发者,我们日常开发过程中无法避免类似getter or setter 这样的代码出现在我们的工程中,又或是引用日志的时候无法避免每个文件中都写一遍

1
private Logger log = LoggerFactory.getLogger(this.getClass());

也有人为了解决这个问题,将其封装成一个工具类,让我们可以通过LogUtil.info("log")这样进行日志的输出,但是使用过的人也许会发现,一般我们打印的日志,日志会输出日志所在类的路径,但是我们使用LogUtil工具类来帮我们输出的话,日志只输出该工具类的路径(当然可以用反射来输出调用LogUtil类的路径),不方便bug排查。

准备工作

使用lombok前需要做两件事:

1、首先是在我们使用的IDE中,安装lombok插件,我这边介绍IDEA的按照过程,

1
File > Settings > Plugins > Browse repositories

然后搜索Lombok Plugin ,然后点击右边绿色的install 按钮进行安装,安装后需要重启IDEA

2、在maven工程中引入lombo 的依赖

1
2
3
4
5
6
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>

接下来就进入激动人心的lombok实战环节。

lombok注解

1、@Slf4j

我们不用自己显示获取log对象,不用自己封装工具类去输出日志,一个注解帮我们搞定

1
2
3
4
5
6
7
8
// private Logger log = LoggerFactory.getLogger(this.getClass());

@Slf4j
public class LogTest {
public static void main(String[] args) {
log.info("==> " + LocalDateTime.now());
}
}

2、@Data

虽然使用IDE为我们的pojo生成gettersetter或者toString这些方法对我们来说习以为常,但是在代码中嵌入一堆gettersetter方法显得不那么优雅,而且我们添加或者修改属性就要重新生成对于的gettersetter方法,所以这里我们可以使用@Getter@Setter注解来帮我们做这些事

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@Getter
@Setter
public class LombokPerson {
private Integer id;
private String name;
private String sex;
}

// 使用idea,jdk1.8 反编译class文件得到如下代码
public class LombokPerson {
private Integer id;
private String name;
private String sex;

public LombokPerson() {
}

public Integer getId() {
return this.id;
}

public String getName() {
return this.name;
}

public String getSex() {
return this.sex;
}

public void setId(Integer id) {
this.id = id;
}

public void setName(String name) {
this.name = name;
}

public void setSex(String sex) {
this.sex = sex;
}
}

其实我们还可以直接在类上使用@Data注解,它的作用比较全,包含了@ToString@EqualsAndHashCode,所有字段的@Getter和所有非final字段的@Setter, @RequiredArgsConstructor,所以我们直接使用@Data注解来替换之前的@Getter@Setter注解

1
2
3
4
5
6
@Data
public class LombokPerson {
private Integer id;
private String name;
private String sex;
}

这里除了gettersetter方法外,还会生成equalscanEqualhashCodetoString,由于代码篇幅较长,这里就不贴出编译后的字节码了,大家可以自行测试

3、@NonNull

其实对于NEP(NullPointerException,后文采用简称NPE),java8已经引入了Optional来尝试解决这个问题,但是这并没有强制检查,使用不当还是会导致NPE,如果你直接使用get方法去获取Optional中包装的空值。

lombok提供的@NonNull,是帮我写了非空判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Demo01 {
public static void main(String[] args) {
String str = null;
checkNull(str);
}
public static void checkNull(@NonNull String msg) {
System.out.println(msg.length());
}
}

// 下面是反编译的class文件
public static void checkNull(@NonNull String msg) {
if (msg == null) {
throw new NullPointerException("msg is marked @NonNull but is null");
} else {
System.out.println(msg.length());
}
}

可以看到lombok帮我添加了一个if判断,如果为空,就抛一个NPE。不过这里和Optional的设计理念不一样,Optional想从根源上去解决Null这个问题,而lombok@NonNull只是保证了程序调用对象方法的时候,会对对象是否为空进行检查,如果为空就抛NPE。

那么使用和不使用都是会抛NPE,那么@NonNull 有什么用处呢,其实通过输出的异常堆栈我们就知道,使用 @NonNull使我们能够快速定位到错误出现的地方msg is marked @NonNull but is null

1
2
3
4
5
6
// 使用 @NonNull
Exception in thread "main" java.lang.NullPointerException: msg is marked @NonNull but is null


// 不使用 @NonNull
Exception in thread "main" java.lang.NullPointerException

4、@Accessors

在介绍生成器模式之前,我们可以试试链式调用风格来初始化我们的对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Accessors(chain = true)
@Setter
@Getter
@ToString
public class Person {

private Integer id;

private String name;
}

// 使用
@Test
public void accessorsTest() {

Person person = new Person();
person.setId(100).setName("jack");
System.out.println(person);
}

为什么我们能连续set来形成链式 调用呢,通过反编译Person.class可以知道,在我们调用Person#setId的时候,给我返回了对象本身–this,所以我们可以继续调用对象的其他set方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Person {
private Integer id;
private String name;

public Person() {
}

public Person setId(Integer id) {
this.id = id;
return this;
}

public Person setName(String name) {
this.name = name;
return this;
}

public Integer getId() {
return this.id;
}

public String getName() {
return this.name;
}

public String toString() {
return "Person(id=" + this.getId() + ", name=" + this.getName() + ")";
}
}

5、@Builder

说到生成器模式我们有些同学可能会感到陌生,但是类似下面这样的代码,我们肯定遇到过

1
2
3
4
Request request = new Request.Builder()
.post(body)
.url(url)
.build();

这是OkHttp构建request对象的api,这种方式来初始化对象并赋值的方式看起来比较优雅,这里我们可以借助lombok提供的@Builder 注解实现,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Builder
@ToString
public class LombokPerson2 {
private Integer id;
private String name;
private String sex;
}

// 测试代码
public static void main(String[] args) {
LombokPerson2 person2 = LombokPerson2
.builder()
.id(1)
.name("laoWang")
.sex("男")
.build();
System.out.println(person2);
}

目前我日常使用的几个注解已经介绍完毕,当然lombok提供的功能不止这些,如果你有兴趣可以自己搜索或者翻看下面这两篇博客。

# Lombok
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×