IT袋

当前位置:主页 > 经验教程 > 建站编程 >

详解Lombok的坑

详解Lombok的坑 Lombok使用中需注意的问题

时间:2024-03-25 20:25:01 来源:IT袋 作者:马勇
导读:详解Lombok的坑,今日IT小知识分享:详解Lombok的坑的相关介绍,接下来一起来看看吧。 不念最近踩了一个lombok的坑,有点意思,给你分享一波。 之前写过一个公共的服务接口,这个接口

详解Lombok的坑

今日IT小知识分享:详解Lombok的坑的相关介绍,接下来一起来看看吧。

不念最近踩了一个lombok的坑,有点意思,给你分享一波。

之前写过一个公共的服务接口,这个接口已经有好几个系统对接并稳定运行了很长一段时间了,长到这个接口都已经交接给别的同事一年多了。

因为是基础服务嘛,相对稳定,所以交出去之后他也一直没有动过这部分代码。

但是有一天有新服务要对接这个接口,同事反馈说遇到一个诡异的问题,这个新服务调用的时候,接口里面报了一个空指针异常。

根据日志来看,那一行代码大概是这样的:

//为了脱敏我用field1、2、3来代替了
if(reqDto.getField1() 
    && reqDto.getField2()!=null
    && reqDto.getField3()!=null){
        //满足条件则执行对应业务逻辑
    }

reqDto 是接口入参对象,有好多字段。具体到 field1、2、3 大概是这样的:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ReqDto { 
    private Boolean field1 = true;
    private String field2;
    private String field3;
}

所以看到这一行抛出了空指针异常,我直接就给出了一个结论:首先排除 field1 为 null,因为有默认值。那只可能 reqDto 传进来的就是 null,导致在 get 字段的时候出现了空指针异常。

但是很不幸,这个结论一秒就被推翻了。

因为 reqDto 是请求入参,在方法入口处选了几个关键字段进行打印。

如果 reqDto 是 null 的话,那么日志打印的时候就会先抛出空指针异常了。

然后我又开始怀疑是部署的代码版本和我们看的版本不一致,可能并不是这一行报错。

和测试同学确认之后,也排除了这个方向。

盯着报错的那一行代码又看了几秒,排除所有不可能之后,我又下了一个结论:调用的时候,传递进来的 field1 主动设值为了 null。

也就是说调用方有这样的代码:

ReqDto reqDto = new ReqDto();
reqDto.setField1(null);

我知道,这样的代码看起来很傻,但是确实只剩下这一种可能了。

于是我去看了调用方构建参数的写法,准备吐槽一波为什么要写设置为 null 这样的坑爹代码。

然而,当时我就被打脸了,调用方的代码是这样的:

ReqDto reqDto = ReqDto.builder()
        .field2("why")
        .field3("max")
        .build();

用的是 builder 模式构建的对象,并不是直接 new 出来的对象。

我一眼看着这个代码也没有发现毛病,虽然没有对 Boolean 类型的 field1 进行设值,但是我有默认值啊。

问调用方为什么不设值,对方的回答也是一句话:我看你有默认值,我本来也是想传 true,但是一看你的默认值就是 true,所以就没有给值了。

对啊,这逻辑无懈可击啊,难道……

是 builder 在里面搞事情了?

于是我里面写了一个代码进行了验证:

详解Lombok的坑

好你个浓眉大眼的 @Builder,果然是你在搞事情。

问题现象基本上就算是定位到了,用 @Builder 注解的时候,丢失默认值了。

所以拿着 “@Builder 默认值” 这样的关键词一搜:

详解Lombok的坑

立马就能找到这样的一个注解:@Builder.Default

对应到我的案例应该是这样的:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ReqDto { 
    @Builder.Default
    private Boolean field1 = true;
    private String field2;
    private String field3;
}

这样,再次运行 Demo 就会发现有默认值了:

详解Lombok的坑

同时我们从两个写法生成的 class 文件中也可以看出一些端倪。

没有@Builder.Default 注解的时候,class 文件中 ReqDtoBuilder 类中关于 field1 字段是这样的:

相关阅读