使用@Builder注解导致线上报NPE的问题

在给一个用@Builder注解的Java Bean的一个属性赋默认值之后,使用build方式构建出来的对象该属性的值是null。

本地模拟

在本地创建一个User类,给vip赋上默认值true。并写了一个测试用例,判断vip是否是null。

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
 public class User {
    private Long id;
    private Boolean vip = true;
 }
 
@Test
public void buildTest(){
    User user = User.builder().id(1L).build();
    assertNull(user.getVip());
}

测试用例可以跑过,说明User的vip并没有赋默认值。这是为什么呢?打开User.class反编译之后的文件可以看到,@Builder注解的作用其实就是帮程序员免去写构造者模式的麻烦,内部生成一个UserBuilder静态内部类。当调用build函数的时候,创建对象。由于生成的代码中,没有给vip字段赋默认值自然拿到的是null。

.....省略部分代码......
 public static class UserBuilder {
        private Long id;
        private Boolean vip;

        UserBuilder() {
        }

        public UserBuilder id(final Long id) {
            this.id = id;
            return this;
        }

        public UserBuilder vip(final Boolean vip) {
            this.vip = vip;
            return this;
        }

        public User build() {
            return new User(this.id, this.vip);
        }

        public String toString() {
            return "User.UserBuilder(id=" + this.id + ", vip=" + this.vip + ")";
        }
    }

解决办法

解决办法也很简单,不需要我们重写User的建造者模式,只要在赋默认值的属性上加上@Builder.Default注解就可以了。

@Data
@Builder
public class User {
    private Long id;
    @Builder.Default
    private Boolean vip = true;
}

再反编译User.class文件文件,发现生成了一个静态方法defaultvip(),该方法返回的就是vip的默认值。调用build方法时会判断vip是否已经设置,没有设置则调用defaultvip()方法赋值。

public class User {
    private Long id;
    private Boolean vip;

    private static Boolean $default$vip() {
        return true;
    }
      public static class UserBuilder {
       ..

        public User build() {
            Boolean vip$value = this.vip$value;
            if (!this.vip$set) {
                vip$value = User.$default$vip();
            }

            return new User(this.id, vip$value);
        }
    }
}      
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值