1. 为什么要使用Builder
《effective jave》书中提到,当一个封装对象中属性过多时,使用builder构造器是一个很好的选择,代码可读性强。但是使用builder又要在对象里写一堆构造器代码,新增了属性或者删除之后还要同步修改构造器代码,非常的繁琐,所以我也不愿意使用。后来,我发现了lombok中有了@Builder注解。
2. @Builder注解的使用
@Getter
@Setter
@Builder
public class Father {
private Integer id;
private String name;
private Integer age;
}
然后看一下编译后的文件内容
public class Father {
private Integer id;
private String name;
private Integer age;
Father(final Integer id, final String name, final Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public static Father.FatherBuilder builder() {
return new Father.FatherBuilder();
}
public Integer getId() {
return this.id;
}
public String getName() {
return this.name;
}
public Integer getAge() {
return this.age;
}
public void setId(final Integer id) {
this.id = id;
}
public void setName(final String name) {
this.name = name;
}
public void setAge(final Integer age) {
this.age = age;
}
public static class FatherBuilder {
private Integer id;
private String name;
private Integer age;
FatherBuilder() {
}
public Father.FatherBuilder id(final Integer id) {
this.id = id;
return this;
}
public Father.FatherBuilder name(final String name) {
this.name = name;
return this;
}
public Father.FatherBuilder age(final Integer age) {
this.age = age;
return this;
}
public Father build() {
return new Father(this.id, this.name, this.age);
}
public String toString() {
return "Father.FatherBuilder(id=" + this.id + ", name=" + this.name + ", age=" + this.age + ")";
}
}
}
生成了全参构造器和构造器模式代码
3.需要注意的坑
仔细看会发现此时并没有生成无参构造,一些框架序列化喜欢用反射new对象,比如现在比较流行的序列化框架Fastjson,这时候就会报错,而反射new对象在编译期是发现不了的,所以容易导致线上问题。此时有几种解决方式
1.同时加上无参和有参的注解,让对象同时生成有参和无参方法(推荐)
@AllArgsConstructor
@NoArgsConstructor
2.自己写无参构造,加上@Tolerate注解让lombok忽略它(这种写法不推荐,ide程序会无法识别出全参构造,导致你写全参构造的时候代码标红,强迫党不能忍)
@Getter
@Setter
@Builder
public class Father {
private Integer id;
private String name;
private Integer age;
@Tolerate
Father() {
}
}
总结
使用@Builder的时候,最好和@AllArgsConstructor,@NoArgsConstructor一起用。