Lombok 类默认值无效

Lombok以简单的注解形式来简化java代码,提高开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法。正因为简化,也有部分开源项目也在使用Lombok,比如Sharding Sphere。

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

@Builder
@Data
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值方便多了,当然也可以再构造函数中直接传入需要的值。但是如果类的属性多了,就会发现使用以及开发效率上要高很多。

然而最近,在项目中使用的时候发现一个问题,如上面的例子,通过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()这个初始化的实例我们的noticedCount值为空。

那么如何才能使默认值有效,Lombok提供了一个注解Default来解决。代码如下

@Builder
@Data
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;这个就是确认是否需要设置默认值。

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

猜你喜欢

转载自www.cnblogs.com/lanweijava/p/10493533.html