代码改变世界

lombok的@Builder注解的坑

2023-02-18 14:42  话猫  阅读(1129)  评论(2编辑  收藏  举报

1.导致无参构造丢失

  • 单独使用@Data注解,是会生成无参数构造方法。
  • 单独使用@Builder注解,发现生成了全属性的构造方法。

@Data和@Builder一起用:我们发现没有了默认的构造方法。如果用@NoArgsConstructor注解会报错!

直接加上这4个注解

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor

2.@Builder注解导致默认值失效

 

 

解决: 只需要在字段上面加上@Builder.Default注解即可,但是这样 new 出来得对象,默认值丢失

 

 

 

3.原因分析

我们使用注解的方式,底层本质就是反射帮我们生成了一系列的setter、getter,所以我们直接打开编译后的target包下面的.class文件,上面的所有原因一目了然!

我们想知道@Data、@Builder等注解底层到底做了什么,直接编译当前文件,即可在生成的.class字节码文件查看具体代码便知道了

@Builder 生成了一个内部类PersonBuilder,并针对每一个属性生成一个同名方法,builder()方法,将每个属性的值塞回到Person类中返回
public class Person {
    private Integer id;
    private String value;

    private static String $default$value() {
        return "yes";
    }

    public static Person.PersonBuilder builder() {
        return new Person.PersonBuilder();
    }

    public Integer getId() {
        return this.id;
    }

    public String getValue() {
        return this.value;
    }

    public void setId(final Integer id) {
        this.id = id;
    }

    public void setValue(final String value) {
        this.value = value;
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Person)) {
            return false;
        } else {
            Person other = (Person)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                Object this$id = this.getId();
                Object other$id = other.getId();
                if (this$id == null) {
                    if (other$id != null) {
                        return false;
                    }
                } else if (!this$id.equals(other$id)) {
                    return false;
                }

                Object this$value = this.getValue();
                Object other$value = other.getValue();
                if (this$value == null) {
                    if (other$value != null) {
                        return false;
                    }
                } else if (!this$value.equals(other$value)) {
                    return false;
                }

                return true;
            }
        }
    }

    protected boolean canEqual(final Object other) {
        return other instanceof Person;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $id = this.getId();
        int result = result * 59 + ($id == null ? 43 : $id.hashCode());
        Object $value = this.getValue();
        result = result * 59 + ($value == null ? 43 : $value.hashCode());
        return result;
    }

    public Person(final Integer id, final String value) {
        this.id = id;
        this.value = value;
    }

    public Person() {
    }

    public String toString() {
        return "Person(id=" + this.getId() + ", value=" + this.getValue() + ")";
    }

    public static class PersonBuilder {
        private Integer id;
        private boolean value$set;
        private String value;

        PersonBuilder() {
        }

        public Person.PersonBuilder id(final Integer id) {
            this.id = id;
            return this;
        }

        public Person.PersonBuilder value(final String value) {
            this.value = value;
            this.value$set = true;
            return this;
        }

        public Person build() {
            String value = this.value;
            if (!this.value$set) {
                value = Person.$default$value();
            }

            return new Person(this.id, value);
        }

        public String toString() {
            return "Person.PersonBuilder(id=" + this.id + ", value=" + this.value + ")";
        }
    }
}