Lombok爱恨纠葛之@Data 和 @Builder 的巨坑,千万别乱用!

新增普通类不使用任何注解
不使用任何注解普通类

编译后的class文件
编译后的class文件
可以看到没有get , set 方法,但有默认生成无参构造方法。

让我们加上@Data注解,看看会发生什么?
加上@Data
加上@Data后的class文件



在这里插入图片描述
可以看到加上@Data后class文件编译后方法都会加上**@Generated**

编译后的文件也会有无参构造方法,方法上加上了@Generated注解

并且生成get , set 方法,及equals、canEqual、hashCode、toString方法。

根据Lombok描述:
Generates getters for all fields, a useful toString method, and hashCode and equals implementations that check all non-transient fields. Will also generate setters for all non-final fields, as well as a constructor (except that no constructor will be generated if any explicitly written constructors already exist).

大概意思就是:
为所有字段生成 get方法、一个有用的 toString 方法以及检查所有非瞬态字段的 hashCode 和 equals 实现。还将为所有非 final 字段生成 setter 以及构造函数(如果已经存在任何显式编写的构造函数,则不会生成任何构造函数)。

显式写上无参构造函数
在这里插入图片描述
可以发现Lombok不会重写这个无参构造函数。
在这里插入图片描述
@Builder 作用是什么样的呢?

单独加上@Builder
在这里插入图片描述
我们会发现@Builder 会生成所有参数的构造函数 。及Builder内部类和toStrin方法。

在这里插入图片描述
但是,没有生成get 、set方法。所以我们只能初始化赋值。无法使用get,set操作。

    Person person = Person.builder()
            .name("zhang san")
            .build();

在这里插入图片描述
将@Data和@Builder两个注解一起使用会发生什么呢?


import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class Person {
    private String name;
    private int age;

}

编译后:


import lombok.Generated;

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

    @Generated
    Person(final String name, final int age) {
        this.name = name;
        this.age = age;
    }

    @Generated
    public static PersonBuilder builder() {
        return new PersonBuilder();
    }

    @Generated
    public String getName() {
        return this.name;
    }

    @Generated
    public int getAge() {
        return this.age;
    }

    @Generated
    public void setName(final String name) {
        this.name = name;
    }

    @Generated
    public void setAge(final int age) {
        this.age = age;
    }

    @Generated
    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 if (this.getAge() != other.getAge()) {
                return false;
            } else {
                Object this$name = this.getName();
                Object other$name = other.getName();
                if (this$name == null) {
                    if (other$name != null) {
                        return false;
                    }
                } else if (!this$name.equals(other$name)) {
                    return false;
                }

                return true;
            }
        }
    }

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

    @Generated
    public int hashCode() {
        int PRIME = true;
        int result = 1;
        result = result * 59 + this.getAge();
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

    @Generated
    public String toString() {
        String var10000 = this.getName();
        return "Person(name=" + var10000 + ", age=" + this.getAge() + ")";
    }

    @Generated
    public static class PersonBuilder {
        @Generated
        private String name;
        @Generated
        private int age;

        @Generated
        PersonBuilder() {
        }

        @Generated
        public PersonBuilder name(final String name) {
            this.name = name;
            return this;
        }

        @Generated
        public PersonBuilder age(final int age) {
            this.age = age;
            return this;
        }

        @Generated
        public Person build() {
            return new Person(this.name, this.age);
        }

        @Generated
        public String toString() {
            return "Person.PersonBuilder(name=" + this.name + ", age=" + this.age + ")";
        }
    }
}

可以发现,有Geter \ Setter方法,但是没有无参构造函数(因为@Data只要有任何显式构造函数存在,它就不会再生成无参构造函数),有所有参数的构造函数
有Builder方法,equals方法,canEqual方法,hashCode方法,toString方法,PersonBuilder内部类。

三个注解一起使用


import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

@Data
@Builder
@AllArgsConstructor
public class Person {
    private String name;
    private int age;

}


import lombok.Generated;

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

    @Generated
    public static PersonBuilder builder() {
        return new PersonBuilder();
    }

    @Generated
    public String getName() {
        return this.name;
    }

    @Generated
    public int getAge() {
        return this.age;
    }

    @Generated
    public void setName(final String name) {
        this.name = name;
    }

    @Generated
    public void setAge(final int age) {
        this.age = age;
    }

    @Generated
    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 if (this.getAge() != other.getAge()) {
                return false;
            } else {
                Object this$name = this.getName();
                Object other$name = other.getName();
                if (this$name == null) {
                    if (other$name != null) {
                        return false;
                    }
                } else if (!this$name.equals(other$name)) {
                    return false;
                }

                return true;
            }
        }
    }

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

    @Generated
    public int hashCode() {
        int PRIME = true;
        int result = 1;
        result = result * 59 + this.getAge();
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

    @Generated
    public String toString() {
        String var10000 = this.getName();
        return "Person(name=" + var10000 + ", age=" + this.getAge() + ")";
    }

    @Generated
    public Person(final String name, final int age) {
        this.name = name;
        this.age = age;
    }

    @Generated
    public static class PersonBuilder {
        @Generated
        private String name;
        @Generated
        private int age;

        @Generated
        PersonBuilder() {
        }

        @Generated
        public PersonBuilder name(final String name) {
            this.name = name;
            return this;
        }

        @Generated
        public PersonBuilder age(final int age) {
            this.age = age;
            return this;
        }

        @Generated
        public Person build() {
            return new Person(this.name, this.age);
        }

        @Generated
        public String toString() {
            return "Person.PersonBuilder(name=" + this.name + ", age=" + this.age + ")";
        }
    }
}

加上@AllArgsConstructor并没有什么变化 ,因为这个注解是生成所有参数的构造函数
在这里插入图片描述
但,我想一个无参的构造函数应该怎么办,
在这里插入图片描述
@NoArgsConstructor注解,生成一个无参的构造函数

那直接加上@NoArgsConstructor注解是否可行?
在这里插入图片描述
看来不行,会和@Builder注解冲突。提示Lombok @Builder needs a proper constructor for this class (Lombok @Builder 需要为此类提供合适的构造函数)

直接显式手写一个无参构造函数会怎么样?
在这里插入图片描述

貌似没报错,但是编译时会报错:无法将类 com.icoderoad.orderchain.entity.Person中的构造器 Person应用到给定类型;。

所以,如果使用@Data + @Builder注解,又想要能够使用无参构造函数,
最终只能是@Data + @Builder + @NoArgsConstructor + @AllArgsConstructor
四个一起配合使用。


import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    private String name;
    private int age;
}

编译后的class


import lombok.Generated;

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

    @Generated
    public static PersonBuilder builder() {
        return new PersonBuilder();
    }

    @Generated
    public String getName() {
        return this.name;
    }

    @Generated
    public int getAge() {
        return this.age;
    }

    @Generated
    public void setName(final String name) {
        this.name = name;
    }

    @Generated
    public void setAge(final int age) {
        this.age = age;
    }

    @Generated
    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 if (this.getAge() != other.getAge()) {
                return false;
            } else {
                Object this$name = this.getName();
                Object other$name = other.getName();
                if (this$name == null) {
                    if (other$name != null) {
                        return false;
                    }
                } else if (!this$name.equals(other$name)) {
                    return false;
                }

                return true;
            }
        }
    }

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

    @Generated
    public int hashCode() {
        int PRIME = true;
        int result = 1;
        result = result * 59 + this.getAge();
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

    @Generated
    public String toString() {
        String var10000 = this.getName();
        return "Person(name=" + var10000 + ", age=" + this.getAge() + ")";
    }

    @Generated
    public Person() {
    }

    @Generated
    public Person(final String name, final int age) {
        this.name = name;
        this.age = age;
    }

    @Generated
    public static class PersonBuilder {
        @Generated
        private String name;
        @Generated
        private int age;

        @Generated
        PersonBuilder() {
        }

        @Generated
        public PersonBuilder name(final String name) {
            this.name = name;
            return this;
        }

        @Generated
        public PersonBuilder age(final int age) {
            this.age = age;
            return this;
        }

        @Generated
        public Person build() {
            return new Person(this.name, this.age);
        }

        @Generated
        public String toString() {
            return "Person.PersonBuilder(name=" + this.name + ", age=" + this.age + ")";
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值