@Builder注解 的不规范使用导致报错

在POJO主类添加Lombok的 @Builder注解后
如果 不加@NoArgsConstructor 和 @AllArgsConstructor两个注解
则会导致该对象 拷贝时出现异常

BeanUtil.copyProperties(test,Test.class);

img

  • 出现原因:

@Builder注解默认用的是全参数构造函数,此时会导致无法new无参对象,为了解决这个问题往往会在@Builder注解的类上加上@NoArgsConstructor注解或者手动加上无参构造函数,此时虽然可以new无参对象了,但却会报题目中这个错误。

  • 解决方案

解决方法很简单,只需在使用@Builder注解的类上再加上@AllArgsConstructor注解即可

  • 原理

可以通过查看字节码文件观察@Builder注解究竟做了什么

@Builder
public class BuilderDemo {

    private String name;

    private int age;
    
}

字节码文件反编译可得:

public class BuilderDemo {
    private String name;
    private int age;

    BuilderDemo(final String name, final int age) {
        this.name = name;
        this.age = age;
    }

    public static BuilderDemo.BuilderDemoBuilder builder() {
        return new BuilderDemo.BuilderDemoBuilder();
    }

    public static class BuilderDemoBuilder {
        private String name;
        private int age;

        BuilderDemoBuilder() {
        }

        public BuilderDemo.BuilderDemoBuilder name(final String name) {
            this.name = name;
            return this;
        }

        public BuilderDemo.BuilderDemoBuilder age(final int age) {
            this.age = age;
            return this;
        }

        public BuilderDemo build() {
            return new BuilderDemo(this.name, this.age);
        }

        public String toString() {
            return "BuilderDemo.BuilderDemoBuilder(name=" + this.name + ", age=" + this.age + ")";
        }
    }
}

可以看到,@Builder注解在BuilderDemo类中生成了一个静态内部类BuilderDemoBuilder,在调用其build方法时是通过BuilderDemo的全参构造器来生成BuilderDemo对象的。而报题目中那个错都是因为BuilderDemo缺少全参构造器导致的。
从反编译的字节码可以看到,在只贴@Builder注解的情况下是默认会生成BuilderDemo类的全参构造器的。那么,什么时候会导致贴了@Builder注解的类缺少全参构造器呢。这里举出最常见的两种情况:

在类上贴了@NoArgsConstructor注解,此时只会生成无参构造器
在类上自己加了个构造器,但方法签名与@Builder注解默认生成的全参构造器不同,此时@Builder注解只会生成无参构造器导致类缺少全参构造器。注:一定要和@Builder注解默认生成的全参构造器完全相同才行,如果加的确实是全参构造器但是参数类型顺序不同也是不行的。同时,最好不要在贴了@Builder注解的类上增加全参构造器,因为这样会覆盖掉@Builder注解默认生成的全参构造器,导致调用其build方法时其实是在调用BuilderDemo自己声明的全参构造器,处理不当容易引发各种bug。

  • 总结

在只贴@Builder注解的情况下是默认会生成该类的全参构造器的,且build方法依赖于生成的该全参构造器。若缺少全参构造器的话便会抛出题目中的异常。各位读者大大们,这个知识点你们get了嘛。

posted @ 2022-11-24 22:19  Chengchenc88  阅读(1490)  评论(0)    收藏  举报