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

當加了@Builder的時候,則會直接出現下面的錯誤,提示沒有無參的構造函數:

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

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

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

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

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

反手我們去看一下反編譯:
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;
}
// 無參構造函數有了
public demoBuilderEntry() {
}
private String name;
private String sex;
}
2. 手寫個無參構造函數并加上@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. 手寫有參無參構造方法
這種方法是最簡單粗暴的,但是代碼可能會沒有那么簡潔:

總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Java面試崗常見問題之ArrayList和LinkedList的區(qū)別
ArrayList和LinkedList作為我們Java中最常使用的集合類,很多人在被問到他們的區(qū)別時,憋了半天僅僅冒出一句:一個是數組一個是鏈表。這樣回答簡直讓面試官吐血。為了讓兄弟們打好基礎,我們通過實際的使用測試,好好說一下ArrayList和LinkedList的區(qū)別這道經典的面試題2022-01-01
springboot 自定義LocaleResolver實現切換語言
我們在做項目的時候,往往有很多項目需要根據用戶的需要來切換不同的語言,使用國際化就可以輕松解決。這篇文章主要介紹了springboot 自定義LocaleResolver切換語言,需要的朋友可以參考下2019-10-10
java基于Apache FTP點斷續(xù)傳的文件上傳和下載
本篇文章主要介紹了java基于Apache FTP點斷續(xù)傳的文件上傳和下載,利用FTP實現文件的上傳和下載,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2016-11-11
jsp+dao+bean+servlet(MVC模式)實現簡單用戶登錄和注冊頁面
這篇文章主要介紹了jsp+dao+bean+servlet(MVC模式)實現簡單用戶登錄和注冊頁面,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-12-12

