Lombok Pojo默认初始值问题

Lombok以注解形式来简化java代码,提高开发效率。比如我们常用的@Builder@Data@AllArgsConstructor@NoArgsConstructor@ToString等。

然最近在迭代中发现Lombok(version:1.16.20或者低于这个版本)的builder模式与new实例化或者反射机制下实例化对象默认值不兼容。这里的默认值不是基本数据类型

Lombok是通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。可以通过反编译查看生成的字节码。例子:

@Builder
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class A {
    int num;
    Integer count;
    Integer noticedCount = 0;
}

使用方式如下

public class Test {
    public static void main(String[] args) {
        A a = A.builder().count(1).noticedCount(2).build();
    }
}

  

这样写看着比以前的new A(),再set值方便多了,当然也可以在构造函数中直接传入需要的值。但是如果类的属性多了,就会发现Lombok使用以及开发效率上要高很多。

然而最近,在项目中使用的时候发现一个bug问题,项目中使用的Lombok的版本号1.16.20。如上面的例子,通过A.builder().build()实例化后,发现a中的noticedCount的默认值为null。究其原因,查看生成的class文件,有个A$Builder.class,使用javap -c A.class查看字节码或者直接将这个class文件拖拽到idea中,查看生成的代码,以下是在idea中展示class的代码

package com.test;
​
public class A$ABuilder {
    private int num;
    private Integer count;
    private Integer noticedCount;
​
    A$ABuilder() {
    }
​
    public A$ABuilder num(int num) {
        this.num = num;
        return this;
    }
​
    public A$ABuilder count(Integer count) {
        this.count = count;
        return this;
    }
​
    public A$ABuilder noticedCount(Integer noticedCount) {
        this.noticedCount = noticedCount;
        return this;
    }
​
    public A build() {
        return new A(this.num, this.count, this.noticedCount);
    }
​
    public String toString() {
        return "A.ABuilder(num=" + this.num + ", count=" + this.count + ", noticedCount=" + this.noticedCount + ")";
    }
}

  

从中看到noticedCount默认值没有。看出A.builder().build()中的build()方法构造A对象的时候是使用内部类的属性值,所以这个初始化的实例我们的noticedCount值为空。

经过查看Lombok下的代码发现有个@Builder.Default根据注释,这个是能解决初始化默认值的。代码如下

@Builder
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class A {
    int num;
    Integer count;
    @Builder.Default
    Integer noticedCount = 0;
} 

再看看生成的A$Builder.class文件的内容如下

package com.test;
​
public class A$ABuilder {
    private int num;
    private Integer count;
    private boolean noticedCount$set;
    private Integer noticedCount;
​
    A$ABuilder() {
    }
​
    public A$ABuilder num(int num) {
        this.num = num;
        return this;
    }
​
    public A$ABuilder count(Integer count) {
        this.count = count;
        return this;
    }
​
    public A$ABuilder noticedCount(Integer noticedCount) {
        this.noticedCount = noticedCount;
        this.noticedCount$set = true;
        return this;
    }
​
    public A build() {
        Integer noticedCount = this.noticedCount;
        if (!this.noticedCount$set) {
            noticedCount = A.access$000();
        }
​
        return new A(this.num, this.count, noticedCount);
    }
​
    public String toString() {
        return "A.ABuilder(num=" + this.num + ", count=" + this.count + ", noticedCount=" + this.noticedCount + ")";
    }
}

可以看到代码中多了private boolean noticedCount$set;这个就是确认是否需要设置默认值。

到这一步你以为就完美了吗??NO.

假如我们在Test方法中增加一行代码,如下,自己可以试试运行的结果看看输出的a与a1的结果

public class Test {
    public static void main(String[] args) {
        A a = A.builder().count(1).noticedCount(2).build();
        System.out.println(a);
        A a1 = new A();
        System.out.println(a1);
    }
}

什么还需要new?有些场景中,比如其他第三方库使用这个类的时候,就不是通过builder模式来实例化对象,第三方库一般都是通过反射机制来实例化,然Lombok给我编译出来的class字节码已经不再是原有的。所以就出现问题了。

Lombok应该也发现了,在1.18.2以上fix这个bug了。大家可以试试。所以建议大家升级下版本

至于Lombok是如何实现的。可以研究下HandleBuilder.里面有具体逻辑

转载于:https://www.cnblogs.com/lanweijava/p/10493533.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,lombok是一个用于简化Java代码的工具库。它通过自动生成常见的Java代码,如getter和setter方法、构造函数等,来减少开发人员的工作量。然而,lombok的版本兼容性可能会导致一些问题。 在引用中,提到了lombok的版本兼容性问题。具体来说,当使用较新版本的lombok时,可能会与某些IDE或编译器不兼容,导致编译错误或无法正常工作。这是因为lombok使用了一些特殊的注解和编译时的代码转换技术,而不是传统的Java代码。 为了解决lombok版本兼容性问题,可以尝试以下方法: 1. 确保使用的lombok版本与IDE或编译器兼容。可以查看lombok的官方文档或相关资源,了解哪些版本与你正在使用的IDE或编译器兼容。 2. 更新IDE或编译器的版本。有时,更新IDE或编译器的版本可以解决与lombok的兼容性问题。确保使用最新的版本,并检查是否有任何与lombok相关的更新或修复。 3. 手动配置IDE或编译器。如果无法解决兼容性问题,可以尝试手动配置IDE或编译器以正确处理lombok的注解和代码转换。这可能涉及到在IDE或编译器中启用lombok插件或设置相关的编译选项。 总之,lombok的版本兼容性问题可能会导致编译错误或无法正常工作。为了解决这些问题,可以尝试使用兼容的lombok版本,更新IDE或编译器的版本,或手动配置IDE或编译器。请根据具体情况选择适合的解决方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值