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

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

2. 先說結(jié)論
由于沒有時間深入查看@Builder的源碼,但是可以從編譯之后的字節(jié)碼得出結(jié)論: 實(shí)體類使用了@Builder,會有全參構(gòu)造函數(shù),沒有默認(rèn)無參構(gòu)造函數(shù),即無法使用默認(rèn)無參構(gòu)造函數(shù)。
解決方法:
- 在實(shí)體類上同時加上:@Builder、@AllArgsConstructor、@NoArgsConstructor
- 手寫全部有參構(gòu)造方法,以及 無參構(gòu)造方法
- 手寫個默認(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;
}
因此,如下圖,一定會報錯:

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

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

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

點(diǎn)擊運(yùn)行,查看結(jié)果的時候,居然可以運(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ò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)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
IDEA中g(shù)it對于指定文件進(jìn)行版本控制的全過程
用戶在IDEA中遇到默認(rèn)提交所有修改的問題,通過配置.gitignore和.git/info/exclude忽略特定文件,并利用vcs.xml指定版本控制范圍,實(shí)現(xiàn)精準(zhǔn)版本管理,本文通過圖文給大家介紹了IDEA中g(shù)it對于指定文件進(jìn)行版本控制的全過程,需要的朋友可以參考下2025-05-05
java基于odbc連接oracle的實(shí)現(xiàn)方法
這篇文章主要介紹了java基于odbc連接oracle的實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了連接操作的具體步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-09-09
Java面試崗常見問題之ArrayList和LinkedList的區(qū)別
ArrayList和LinkedList作為我們Java中最常使用的集合類,很多人在被問到他們的區(qū)別時,憋了半天僅僅冒出一句:一個是數(shù)組一個是鏈表。這樣回答簡直讓面試官吐血。為了讓兄弟們打好基礎(chǔ),我們通過實(shí)際的使用測試,好好說一下ArrayList和LinkedList的區(qū)別這道經(jīng)典的面試題2022-01-01
MyBatis框架關(guān)聯(lián)映射實(shí)例詳解
這篇文章主要介紹了MyBatis框架關(guān)聯(lián)映射,關(guān)系映射主要處理復(fù)雜的SQl查詢,如子查詢,多表聯(lián)查等復(fù)雜查詢,應(yīng)用此種需求時可以考慮使用,需要的朋友可以參考下2022-11-11
springboot 自定義LocaleResolver實(shí)現(xiàn)切換語言
我們在做項(xiàng)目的時候,往往有很多項(xiàng)目需要根據(jù)用戶的需要來切換不同的語言,使用國際化就可以輕松解決。這篇文章主要介紹了springboot 自定義LocaleResolver切換語言,需要的朋友可以參考下2019-10-10
java基于Apache FTP點(diǎn)斷續(xù)傳的文件上傳和下載
本篇文章主要介紹了java基于Apache FTP點(diǎn)斷續(xù)傳的文件上傳和下載,利用FTP實(shí)現(xiàn)文件的上傳和下載,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2016-11-11
通過實(shí)例學(xué)習(xí)JAVA對象轉(zhuǎn)成XML輸出
這篇文章主要介紹了通過實(shí)例學(xué)習(xí)JAVA對象轉(zhuǎn)成XML輸出,做流程圖的項(xiàng)目時,新的流程定義為xml的,需要對xml與java對象進(jìn)行互轉(zhuǎn),下面我們來深入學(xué)習(xí),需要的朋友可以參考下2019-06-06
jsp+dao+bean+servlet(MVC模式)實(shí)現(xiàn)簡單用戶登錄和注冊頁面
這篇文章主要介紹了jsp+dao+bean+servlet(MVC模式)實(shí)現(xiàn)簡單用戶登錄和注冊頁面,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
SpringBoot實(shí)現(xiàn)性能翻倍的五種配置方案
在當(dāng)今高并發(fā)的互聯(lián)網(wǎng)環(huán)境下,微服務(wù)架構(gòu)的性能優(yōu)化成為了開發(fā)者必須面對的挑戰(zhàn),SpringBoot作為Java生態(tài)中最流行的微服務(wù)框架之一,其默認(rèn)配置雖然能滿足大多數(shù)場景需求,但在極端性能要求下往往顯得力不從心,本文將揭示5個常被開發(fā)者忽略的SpringBoot配置項(xiàng)2026-01-01

