使用@Builder導致無法創(chuàng)建無參構(gòu)造方法的解決
1. 前言
在創(chuàng)建實體類的時候,有時候參數(shù)過于多,如果使用有參數(shù)的構(gòu)造函數(shù),實在看起來不是很優(yōu)雅,一般都會想使用@Builder構(gòu)建者模式來進行創(chuàng)建對象,不僅僅優(yōu)雅,而且還方便。
當偶然機會發(fā)現(xiàn),如果使用了@Builder,該實體類會失去無參構(gòu)造方法。
具體現(xiàn)象如下:
當不加任何注解的時候,完成正常:

當加了@Builder的時候,則會直接出現(xiàn)下面的錯誤,提示沒有無參的構(gòu)造函數(shù):

2. 先說結(jié)論
由于沒有時間深入查看@Builder的源碼,但是可以從編譯之后的字節(jié)碼得出結(jié)論: 實體類使用了@Builder,會有全參構(gòu)造函數(shù),沒有默認無參構(gòu)造函數(shù),即無法使用默認無參構(gòu)造函數(shù)。
解決方法:
- 在實體類上同時加上:@Builder、@AllArgsConstructor、@NoArgsConstructor
- 手寫全部有參構(gòu)造方法,以及 無參構(gòu)造方法
- 手寫個默認無參構(gòu)造方法,并加上@Tolerate
@Builder
public class demoBuilderEntry {
private String name;
private String sex;
@Tolerate
public demoBuilderEntry() {
}
}
3. 演示
若不知道怎么查看java反編譯字節(jié)碼內(nèi)容,可以看一下:
Java如何進行反編譯生成.java文件(javap、jad下載安裝使用)
1.當實體類不加任何東西:
public class demoBuilderEntry {
private String name;
private String sex;
}
可以看見是默認有無參構(gòu)造函數(shù)
public class demoBuilderEntry {
public demoBuilderEntry() {
}
private String name;
private String sex;
}
2.當實體類加上@Builder注解:
@Builder
public class demoBuilderEntry {
private String name;
private String sex;
}
可以看出:無參構(gòu)造函數(shù)已不存在,只剩全參構(gòu)造函數(shù):
public class demoBuilderEntry {
public static class demoBuilderEntryBuilder {
public demoBuilderEntryBuilder name(String name) {
this.name = name;
return this;
}
public demoBuilderEntryBuilder sex(String sex) {
this.sex = sex;
return this;
}
public demoBuilderEntry build() {
return new demoBuilderEntry(name, sex);
}
public String toString() {
return (new StringBuilder()).append("demoBuilderEntry.demoBuilderEntryBuilder(name=").append(name).append(", sex=").append(sex).append(")").toString();
}
private String name;
private String sex;
demoBuilderEntryBuilder() {
}
}
demoBuilderEntry(String name, String sex) {
this.name = name;
this.sex = sex;
}
public static demoBuilderEntryBuilder builder() {
return new demoBuilderEntryBuilder();
}
private String name;
private String sex;
}
因此,如下圖,一定會報錯:

有人會說:沒有無參怎么了,也沒有什么事情,反正需要構(gòu)造。
但像spring這種,我們可以從配置文件中注入屬性,如@ConfigurationProperties,它們的做法是先創(chuàng)建該類對象,使用無參構(gòu)造函數(shù),然后再調(diào)用set方法,此時,你沒有默認無參構(gòu)造方法,必然會失敗,畢竟連對象都沒有創(chuàng)建成功。
具體失敗案例可以看:實體類使用@Builder,導致@ConfigurationProperties注入屬性失敗
3.如果需要無參構(gòu)造函數(shù),那就手動添加,在實體類上,再加上@NoArgsConstructor也無效。
根據(jù)下圖可以看見,似乎沒有報錯

當運行的時候,則報錯如下:與實際參數(shù)列表不符,顯然是無法通過加@NoArgsConstructor創(chuàng)建默認無參構(gòu)造函數(shù)。

4. 解決方法
1. 在實體類上再加上@AllArgsConstructor即可
根據(jù)下圖查看,似乎也沒有問題:

點擊運行,查看結(jié)果的時候,居然可以運行成功如下:

反手我們?nèi)タ匆幌路淳幾g:
public class demoBuilderEntry {
public static class demoBuilderEntryBuilder {
// builder 的代碼省略,沒有粘出來
}
public static void main(String args[]) {
System.out.println(new demoBuilderEntry());
}
public static demoBuilderEntryBuilder builder() {
return new demoBuilderEntryBuilder();
}
public demoBuilderEntry(String name, String sex) {
this.name = name;
this.sex = sex;
}
// 無參構(gòu)造函數(shù)有了
public demoBuilderEntry() {
}
private String name;
private String sex;
}
2. 手寫個無參構(gòu)造函數(shù)并加上@Tolerate
@Tolerate:中文:容許,通俗來說,被該注解加上的方法,讓lombok容許它們存在。
/**
* Put on any method or constructor to make lombok pretend it doesn't exist,
* i.e., to generate a method which would otherwise be skipped due to possible conflicts.
*/
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.SOURCE)
public @interface Tolerate {
}
測試:

3. 手寫有參無參構(gòu)造方法
這種方法是最簡單粗暴的,但是代碼可能會沒有那么簡潔:

總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis-Plus自動生成的數(shù)據(jù)庫id過長的解決
這篇文章主要介紹了Mybatis-Plus自動生成的數(shù)據(jù)庫id過長的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
Java結(jié)合redistemplate使用分布式鎖案例講解
在Java中使用RedisTemplate結(jié)合Redis來實現(xiàn)分布式鎖是一種常見的做法,特別適用于微服務架構(gòu)或多實例部署的應用程序中,以確保數(shù)據(jù)的一致性和避免競態(tài)條件,下面給大家分享使用Spring Boot和RedisTemplate實現(xiàn)分布式鎖的案例,感興趣的朋友一起看看吧2024-08-08
Java引用傳遞實現(xiàn)方式以及與值傳遞的區(qū)別
這篇文章主要給大家介紹了關(guān)于Java引用傳遞實現(xiàn)方式以及與值傳遞的區(qū)別的相關(guān)資料,引用傳遞指在調(diào)用函數(shù)時將實際參數(shù)的地址直接傳遞到函數(shù)中,那么在函數(shù)中對參數(shù)所進行的修改,將影響到實際參數(shù),需要的朋友可以參考下2023-09-09
SpringBoot集成nacos動態(tài)刷新數(shù)據(jù)源的實現(xiàn)示例
這篇文章主要介紹了SpringBoot集成nacos動態(tài)刷新數(shù)據(jù)源的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-12-12
Spring Cloud 系列之負載均衡 Ribbon的示例代碼
Ribbon 是 Netflix 發(fā)布的負載均衡器,它有助于控制 HTTP 和 TCP 客戶端的行為。這篇文章主要介紹了Spring Cloud 系列之負載均衡 Ribbon的示例代碼,需要的朋友可以參考下2020-11-11
使用mybatisPlus生成oracle自增序列遇到的坑及解決
這篇文章主要介紹了使用mybatisPlus生成oracle自增序列遇到的坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03

