一、@Builder注解
資料來(lái)源: http://fendou.net.cn/index.php/a/369
https://blog.csdn.net/qq_39249094/article/details/120881578
作用于類(lèi),將其變成建造者模式
可以以鏈的形式調(diào)用
初始化實(shí)例對(duì)象生成的對(duì)象是不可以變的,可以在創(chuàng)建對(duì)象的時(shí)候進(jìn)行賦值(如果想改變的話需要在@Builder后面添加參數(shù)toBuilder=true)
需要在原來(lái)的基礎(chǔ)上修改可以加 set 方法,final 字段可以不需要初始化
生成一個(gè)全參的構(gòu)造函數(shù)
1.0 Lombok坐標(biāo)
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>0.10.2</version>
</dependency>
提供在設(shè)計(jì)數(shù)據(jù)實(shí)體時(shí),對(duì)外保持private setter,而對(duì)屬性的賦值采用Builder的方式,這種方式最優(yōu)雅,也更符合封裝的原則,不對(duì)外公開(kāi)屬性的寫(xiě)操作
@Builder聲明實(shí)體,表示可以進(jìn)行Builder方式初始化
@Value注解,表示只公開(kāi)getter,對(duì)所有屬性的setter都封閉,即private修飾,所以它不能和@Builder一起用
1.1 注解使用
@Builder
@Getter
@Data
publicclassUserInfo {
private String name;
privateStringemail;
?
@Override
public String toString() {
return"UserInfo{"+
"name='"+name+'\''+
", email='"+email+'\''+
'}';
}
?
public static void main(String[] args) {
UserInfo userInfo = UserInfo.builder().build();
System.out.println("userInfo---->"+userInfo);
?
UserInfo userInfo1 = UserInfo.builder()
.name("zzl")
.email("bgood@sina.com")
.build();
System.out.println("userInfo1---->"+userInfo1);
}
}

1.2 注解的屬性介紹
1.2.1 toBuilder
設(shè)置為 true 可以對(duì)這個(gè)對(duì)象進(jìn)行拷貝生成新的對(duì)象,可以再修改,默認(rèn)為 false
怎么設(shè)置為true?
@Builder(toBuilder = true)
我們使用UserInfo.builder().build()創(chuàng)建出來(lái)之后,還可以修改對(duì)象的內(nèi)容么(不使用set方法)?

我們此時(shí)發(fā)現(xiàn)如果想對(duì)已經(jīng)構(gòu)建了的對(duì)象在修改的話,會(huì)出錯(cuò),并找不到這個(gè)方法,我們只需要在類(lèi)注解上添加@Builder(toBuilder = true)即可
@Builder(toBuilder=true)
@Getter
public class UserInfo {}
userInfo = userInfo.toBuilder()
.name("OK")
.email("zgood@sina.com")
.build();
1.2.2 @Builder.Default 注解
非 final 的字段可以有默認(rèn)值
@Builder.Default
private String name ="劉亦菲";
我們下面雖然沒(méi)有對(duì)name賦值,但是輸出時(shí)”name“依然會(huì)時(shí)"劉亦菲"
UserInfo userInfo = UserInfo.builder().build();
System.out.println("userInfo---->"+userInfo);
final字段加不加Default都可以初始化成功,因?yàn)閒inal字段如果第一次不是null的話,就不可修改(簡(jiǎn)單的來(lái)說(shuō),final字段有了初始值之后就不可更改)
private final Integerage=18;
這兩種寫(xiě)法都可以
@Builder.Default
private final Integer age;
1.2.3 buildMethodName
指定創(chuàng)建實(shí)體類(lèi)的方法名,默認(rèn)值為 build
當(dāng)我們指定內(nèi)部靜態(tài)類(lèi)的方法名為“test”的時(shí)候,發(fā)現(xiàn)下面已經(jīng)開(kāi)始報(bào)錯(cuò)了

當(dāng)我們把這里改成test之后便不會(huì)報(bào)錯(cuò)了

1.2.4 builderMethodName
指定創(chuàng)建內(nèi)部靜態(tài)類(lèi)的方法名,默認(rèn)值為 builder

1.2.5 builderClassName
指定內(nèi)部靜態(tài)的類(lèi)名,默認(rèn)值為 “”,默認(rèn)創(chuàng)建的類(lèi)名為 thisclassBuilder
這個(gè)我不太懂,不知道怎么演示
1.2.6 access
設(shè)置 builderMethodName 的訪問(wèn)權(quán)限修飾符,默認(rèn)為 public
共有 PUBLIC、MODULE、PROTECTED、PACKAGE、PRIVATE,其中 MODULE 是 Java 9 的新特性
access = AccessLevel.PUBLIC
1.2.7 setterPrefix
設(shè)置 setter 方法的前綴,默認(rèn)為 “”
1.3 處理添加無(wú)參構(gòu)造函數(shù)報(bào)錯(cuò)時(shí)報(bào)錯(cuò)
@Builder 會(huì)生成一個(gè)全參構(gòu)造方法,因此就沒(méi)有了無(wú)參構(gòu)造方法,但當(dāng)我們遇到需要無(wú)參構(gòu)造方法時(shí)就會(huì)發(fā)生問(wèn)題,這個(gè)時(shí)候手寫(xiě)或者加上 @NoArgsConstructor 都會(huì)報(bào)錯(cuò)

1.3.1 處理方案1
加上 @AllArgsConstructor

1.3.2 處理方案2
使用 @Builder 對(duì)一個(gè) DTO 實(shí)現(xiàn)一個(gè)構(gòu)造器,但是在做 Json 反序列化的時(shí)候發(fā)生錯(cuò)誤,原因就是缺少無(wú)參公共的構(gòu)造函數(shù),而手動(dòng)寫(xiě)一個(gè)無(wú)參構(gòu)造函數(shù)的時(shí)候編譯錯(cuò)誤,就是和 @Builder 沖突
雖然標(biāo)準(zhǔn)的 @Builder 沒(méi)法是需要私有化構(gòu)造函數(shù)的,但是在某些場(chǎng)景下我們需要對(duì)這種標(biāo)準(zhǔn)變形,這個(gè)時(shí)候 lombok 提供了 @Tolerate 實(shí)現(xiàn)對(duì)沖突的兼容
使用@Tolerate注解
我們手動(dòng)添加一個(gè)無(wú)參構(gòu)造函數(shù),但是當(dāng)運(yùn)行之后就會(huì)出現(xiàn)錯(cuò)誤

但是當(dāng)我們?cè)跓o(wú)參構(gòu)造函數(shù)上添加@Tolerate注解之后就可以正常運(yùn)行

1.4 @Builder內(nèi)部
創(chuàng)建一個(gè)名為 ThisClassBuilder 的內(nèi)部靜態(tài)類(lèi),并具有和實(shí)體類(lèi)相同的屬性(稱(chēng)為構(gòu)建器)
在構(gòu)建器中:對(duì)于目標(biāo)類(lèi)中的所有的屬性和未初始化的 final 字段,都會(huì)在構(gòu)建器中創(chuàng)建對(duì)應(yīng)屬性
在構(gòu)建器中:創(chuàng)建一個(gè)無(wú)參的 default 構(gòu)造函數(shù)
在構(gòu)建器中:實(shí)體類(lèi)中的每個(gè)參數(shù),都會(huì)對(duì)應(yīng)創(chuàng)建類(lèi)似于 setter 的方法,方法名與該參數(shù)名相同。 并且返回值是構(gòu)建器本身(便于鏈?zhǔn)秸{(diào)用)
在構(gòu)建器中:會(huì)創(chuàng)建一個(gè) build 方法,調(diào)用 build 方法,就會(huì)根據(jù)設(shè)置的值進(jìn)行創(chuàng)建實(shí)體對(duì)象
在構(gòu)建器中:會(huì)生成一個(gè) toString 方法文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-769941.html
在實(shí)體類(lèi)中:會(huì)創(chuàng)建一個(gè) builder 方法,它的目的是用來(lái)創(chuàng)建構(gòu)建器文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-769941.html
@Builder
public class User {
private String username;
private String password;
}
public class User {
private String username;
private String password;
?
?
User(Stringusername, Stringpassword) {
this.username=username;
this.password=password;
}
// 在實(shí)體類(lèi)中會(huì)創(chuàng)建一個(gè) builder 方法,它的目的是用來(lái)創(chuàng)建構(gòu)建器
public static User.UserBuilder builder() {
returnnewUser.UserBuilder();
}
// 構(gòu)建器
public static class UserBuilder {
//在構(gòu)建器中:對(duì)于目標(biāo)類(lèi)中的所有的屬性和未初始化的 final 字段,都會(huì)在構(gòu)建器中創(chuàng)建對(duì)應(yīng)屬性
private String username;
private String password;
//在構(gòu)建器中:創(chuàng)建一個(gè)無(wú)參的 default 構(gòu)造函數(shù)
UserBuilder() {
}
?
//在構(gòu)建器中:實(shí)體類(lèi)中的每個(gè)參數(shù),都會(huì)對(duì)應(yīng)創(chuàng)建類(lèi)似于 setter 的方法,方法名與該參數(shù)名相同。 并且返回值是構(gòu)建器本身(便于鏈?zhǔn)秸{(diào)用)
public User.UserBuilde rusername(Stringusername) {
this.username=username;
returnthis;
}
?
public User.UserBuilderpassword(Stringpassword) {
this.password=password;
returnthis;
}
//在構(gòu)建器中:會(huì)創(chuàng)建一個(gè) build 方法,調(diào)用 build 方法,就會(huì)根據(jù)設(shè)置的值進(jìn)行創(chuàng)建實(shí)體對(duì)象
publicUserbuild() {
return newUser(this.username, this.password);
}
//在構(gòu)建器中:會(huì)生成一個(gè) toString 方法
public String toString() {
return"User.UserBuilder(username="+this.username+", password="+this.password+")";
}
}
}
到了這里,關(guān)于@Builder注解使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!