使用@Builder導(dǎo)致無法創(chuàng)建無參構(gòu)造方法的解決
1. 前言
在創(chuàng)建實(shí)體類的時(shí)候,有時(shí)候參數(shù)過于多,如果使用有參數(shù)的構(gòu)造函數(shù),實(shí)在看起來不是很優(yōu)雅,一般都會(huì)想使用@Builder構(gòu)建者模式來進(jìn)行創(chuàng)建對(duì)象,不僅僅優(yōu)雅,而且還方便。
當(dāng)偶然機(jī)會(huì)發(fā)現(xiàn),如果使用了@Builder,該實(shí)體類會(huì)失去無參構(gòu)造方法。
具體現(xiàn)象如下:
當(dāng)不加任何注解的時(shí)候,完成正常:
當(dāng)加了@Builder的時(shí)候,則會(huì)直接出現(xiàn)下面的錯(cuò)誤,提示沒有無參的構(gòu)造函數(shù):
2. 先說結(jié)論
由于沒有時(shí)間深入查看@Builder的源碼,但是可以從編譯之后的字節(jié)碼得出結(jié)論: 實(shí)體類使用了@Builder,會(huì)有全參構(gòu)造函數(shù),沒有默認(rèn)無參構(gòu)造函數(shù),即無法使用默認(rèn)無參構(gòu)造函數(shù)。
解決方法:
- 在實(shí)體類上同時(shí)加上:@Builder、@AllArgsConstructor、@NoArgsConstructor
- 手寫全部有參構(gòu)造方法,以及 無參構(gòu)造方法
- 手寫個(gè)默認(rèn)無參構(gòu)造方法,并加上@Tolerate
@Builder public class demoBuilderEntry { private String name; private String sex; @Tolerate public demoBuilderEntry() { } }
3. 演示
若不知道怎么查看java反編譯字節(jié)碼內(nèi)容,可以看一下:
Java如何進(jìn)行反編譯生成.java文件(javap、jad下載安裝使用)
1.當(dāng)實(shí)體類不加任何東西:
public class demoBuilderEntry { private String name; private String sex; }
可以看見是默認(rèn)有無參構(gòu)造函數(shù)
public class demoBuilderEntry { public demoBuilderEntry() { } private String name; private String sex; }
2.當(dāng)實(shí)體類加上@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; }
因此,如下圖,一定會(huì)報(bào)錯(cuò):
有人會(huì)說:沒有無參怎么了,也沒有什么事情,反正需要構(gòu)造。
但像spring這種,我們可以從配置文件中注入屬性,如@ConfigurationProperties,它們的做法是先創(chuàng)建該類對(duì)象,使用無參構(gòu)造函數(shù),然后再調(diào)用set方法,此時(shí),你沒有默認(rèn)無參構(gòu)造方法,必然會(huì)失敗,畢竟連對(duì)象都沒有創(chuàng)建成功。
具體失敗案例可以看:實(shí)體類使用@Builder,導(dǎo)致@ConfigurationProperties注入屬性失敗
3.如果需要無參構(gòu)造函數(shù),那就手動(dòng)添加,在實(shí)體類上,再加上@NoArgsConstructor也無效。
根據(jù)下圖可以看見,似乎沒有報(bào)錯(cuò)
當(dāng)運(yùn)行的時(shí)候,則報(bào)錯(cuò)如下:與實(shí)際參數(shù)列表不符,顯然是無法通過加@NoArgsConstructor創(chuàng)建默認(rèn)無參構(gòu)造函數(shù)。
4. 解決方法
1. 在實(shí)體類上再加上@AllArgsConstructor即可
根據(jù)下圖查看,似乎也沒有問題:
點(diǎn)擊運(yùn)行,查看結(jié)果的時(shí)候,居然可以運(yùn)行成功如下:
反手我們?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è)無參構(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 { }
測(cè)試:
3. 手寫有參無參構(gòu)造方法
這種方法是最簡(jiǎn)單粗暴的,但是代碼可能會(huì)沒有那么簡(jiǎn)潔:
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis-Plus自動(dòng)生成的數(shù)據(jù)庫id過長(zhǎng)的解決
這篇文章主要介紹了Mybatis-Plus自動(dòng)生成的數(shù)據(jù)庫id過長(zhǎng)的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java結(jié)合redistemplate使用分布式鎖案例講解
在Java中使用RedisTemplate結(jié)合Redis來實(shí)現(xiàn)分布式鎖是一種常見的做法,特別適用于微服務(wù)架構(gòu)或多實(shí)例部署的應(yīng)用程序中,以確保數(shù)據(jù)的一致性和避免競(jìng)態(tài)條件,下面給大家分享使用Spring Boot和RedisTemplate實(shí)現(xiàn)分布式鎖的案例,感興趣的朋友一起看看吧2024-08-08mybatis?log4j2打印sql+日志實(shí)例代碼
在學(xué)習(xí)mybatis的時(shí)候,如果用log4j2來協(xié)助查看調(diào)試信息,則會(huì)大大提高學(xué)習(xí)的效率,加快debug速度,下面這篇文章主要給大家介紹了關(guān)于mybatis?log4j2打印sql+日志的相關(guān)資料,需要的朋友可以參考下2022-08-08Java引用傳遞實(shí)現(xiàn)方式以及與值傳遞的區(qū)別
這篇文章主要給大家介紹了關(guān)于Java引用傳遞實(shí)現(xiàn)方式以及與值傳遞的區(qū)別的相關(guān)資料,引用傳遞指在調(diào)用函數(shù)時(shí)將實(shí)際參數(shù)的地址直接傳遞到函數(shù)中,那么在函數(shù)中對(duì)參數(shù)所進(jìn)行的修改,將影響到實(shí)際參數(shù),需要的朋友可以參考下2023-09-09SpringBoot集成nacos動(dòng)態(tài)刷新數(shù)據(jù)源的實(shí)現(xiàn)示例
這篇文章主要介紹了SpringBoot集成nacos動(dòng)態(tài)刷新數(shù)據(jù)源的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Spring Cloud 系列之負(fù)載均衡 Ribbon的示例代碼
Ribbon 是 Netflix 發(fā)布的負(fù)載均衡器,它有助于控制 HTTP 和 TCP 客戶端的行為。這篇文章主要介紹了Spring Cloud 系列之負(fù)載均衡 Ribbon的示例代碼,需要的朋友可以參考下2020-11-11使用mybatisPlus生成oracle自增序列遇到的坑及解決
這篇文章主要介紹了使用mybatisPlus生成oracle自增序列遇到的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03