@Builder
是 lombok
中的註解。可以使用builder()
構造的Person.PersonBuilder
物件進行鏈式呼叫,給所有屬性依次賦值。
Person person1 = Person.builder()
.name("張三")
.age(20)
.build();
System.out.println(person1); // Person(name=張三, age=20)
System.out.println(Person.builder()); // Person.PersonBuilder(name=null, age=null)
檔案中給了案例,在實體類上新增 @Builder
後,實體類會被改造成如下的結構:
Before:
@Builder
class Example<T> {
private T foo;
private final String bar;
}
After:
class Example<T> {
private T foo;
private final String bar;
// 私有的全引數建構函式
private Example(T foo, String bar) {
this.foo = foo;
this.bar = bar;
}
public static <T> ExampleBuilder<T> builder() {
return new ExampleBuilder<T>();
}
public static class ExampleBuilder<T> {
private T foo;
private String bar;
private ExampleBuilder() {}
public ExampleBuilder foo(T foo) {
this.foo = foo;
return this;
}
public ExampleBuilder bar(String bar) {
this.bar = bar;
return this;
}
@java.lang.Override public String toString() {
return "ExampleBuilder(foo = " + foo + ", bar = " + bar + ")";
}
public Example build() {
return new Example(foo, bar);
}
}
}
原始碼如下:
@Target({TYPE, METHOD, CONSTRUCTOR})
@Retention(SOURCE)
public @interface Builder {
@Target(FIELD)
@Retention(SOURCE)
public @interface Default {}
String builderMethodName() default "builder";
String buildMethodName() default "build";
String builderClassName() default "";
boolean toBuilder() default false;
AccessLevel access() default lombok.AccessLevel.PUBLIC;
String setterPrefix() default "";
@Target({FIELD, PARAMETER})
@Retention(SOURCE)
public @interface ObtainVia {
String field() default "";
String method() default "";
boolean isStatic() default false;
}
}
該註解預設變數的名稱是一個複數,並且嘗試生成該變數的奇數形式。例如 List<String> skills
,會新增3個方法:
skill(String skill)
新增單個元素skills(List<String> skillList)
新增一個集合clearSkills()
清空集合,並且將未初始化的集合初始化未空集合。如果無法計算得到變數名稱的奇數形式,則會提示報錯資訊。使用者可以手動指定單數形式的方法名:
@Singular("skill")
private List<String> skillList;
這時會生成skill(String skill)
、 skillList(List<String> skillList)
和 clearSkillList()
三個方法。
使用 @Builder.Default
設定預設值,構建物件時可以不用呼叫`name()方法。(呼叫後會覆蓋預設值)
@Builder.Default
private String name = "zhangsan";
@Builder
註解無法解析父類別的屬性,而@SuperBuilder
可以讀取父類別的屬性。使用時需要在子類和父類別上都加上這個註解。
@SuperBuilder
public class Male extends Person{
}
@SuperBuilder
public class Person {
@Builder.Default
private String name = "zhangsan";
private Integer age;
@Singular("skillList")
private List<String> skillList;
}
使用 @SuperBuilder(toBuilder=true)
可以使用已有的物件構建新的物件,舊物件的屬性值會被保留和覆蓋。注意: 子類和父類別都需要加上toBuilder=true
Male man = Male.builder()
.name("張三")
.age(20)
.build();
Male man2 = man.toBuilder()
.age(30)
.build();