Lombok你也許不知道的 @Builder 坑坑!
theme: scrolls-light
這是我參與11月更文挑戰的第17天,活動詳情檢視:2021最後一次更文挑戰
🤞 個人主頁:@青Cheng序員石頭
🤞 粉絲福利:加粉絲群 一對一問題解答,獲取免費的豐富簡歷模板、提高學習資料等,做好新時代的卷卷王!
Lombok,使我們提供我們生產效率的一個強大的利器,其通過簡單的註解來實現精簡程式碼,消除冗長程式碼和提高開發效率的目的。我很喜歡使用的一個註解是@Builder,這個註解能讓我很輕鬆的使用構造器模式,這篇文章記錄如何在子類中使用@Builder避免一個常見的坑坑。
一、問題
對於下面這兩個類,一個父類,一個子類。兩個類都想使用@Builder註解,用於使用構造器模式去構造一個物件。
```java @Getter @ToString public class Parent {
private long id;
private String name;
@Builder
@Getter
@ToString
static class Child extends Parent{
private String value;
}
} ```
當我們嘗試編譯上面的程式碼時,會報錯,報錯的內容如下。
無法將類 <包路徑>.Parent中的構造器 Parent應用到給定型別;
這個原因是,這是由於Lombok
未考慮父類的欄位,而只考慮到當前子類的欄位。
二、解決方案
解決辦法有很多種,最簡單的一種是我們在子類的建構函式中包含父類的欄位,並且對建構函式使用@Builder
的註解。
```java
@Getter
@AllArgsConstructor
@ToString
public class Parent {
private long id;
private String name;
@Getter
@ToString
static class Child extends Parent{
private String value;
@Builder
public Child(long id,String name,String value){
super(id,name);
this.value = value;
}
}
}
這種方式能解決上面的問題,但是如果我們想對父類使用`@Builder`的註解,如下面的程式碼所示。
java
@Getter
@AllArgsConstructor
@ToString
@Builder
public class Parent {
...
}
```
編譯的時候又會報另一個錯誤。
<包路徑>.Child()無法覆蓋<包路徑>.Parent中的builder()
這個原因是,子類嘗試申明具有跟父類相同名稱的builder,說的通俗一定就是builder重名了。我們可以為子類替換一個構造器名字去解決這個問題,如下面的程式碼所示,為子類的Builder自定義一個名稱。
java
@Builder(builderMethodName = "childBuilder")
public Child(long id,String name,String value){
super(id,name);
this.value = value;
}
這個問題是解決了,機智的同學又會問了,那麼如果我繼承更深的層次呢,比如還有另外的類要繼承Child
類,也想使用Builder模式,怎麼辦呢?能想到最簡單的辦法就是像上面一樣,將繼承類的建構函式改寫,支援父類所有的欄位。
除了這個辦法,還有什麼簡單快捷的方法呢?答案是Lombok本身提供了行之有效的解決辦法。
三、更好的解決方案
Lombok1.18
版引入了@SuperBuilder
註解,使用這個註解同時註解父類和子類可以解決我們上面遇到的問題。
``` @Getter @AllArgsConstructor @ToString @SuperBuilder public class Parent {
private long id;
private String name;
@Getter
@ToString
@SuperBuilder
static class Child extends Parent{
private String value;
}
@Getter
@ToString
@SuperBuilder
static class ChildSChild extends Child{
private String personality;
}
}
``
需要注意兩點:
1.
@SuperBuilder和
@Builder在父類和子類中不能混用
2.
@SuperBuilder`在所有的父類和子類中都必須使用上,缺一不可。
四、總結
使用Lombok
的目的是為了提供我們工作效率,建議在使用這些便捷工具時,要仔細理解一下官方的解釋說明,其實很多使用技巧和避坑指南都寫在了官方文件上。
少年,沒看夠?點選石頭的詳情介紹,隨便點點看看,說不定有驚喜呢?歡迎支援點贊/關注/評論,有你們的支援是我更文最大的動力,多謝啦!
- 多雲 Vs 混合雲 (一)
- DDD | 領域驅動設計 Vs 微服務
- DDD | 領域驅動設計 Vs 敏捷 Vs 面向物件
- AWS & Azure & GCP 選擇
- 機器是如何學習的?(半監督式學習和其它方式)
- 機器是如何學習的?(非監督式學習)
- 機器是如何學習的?(監督式學習)
- 安全 | 聊聊挖礦哪些事兒(一)
- 機器學習的入門學習資料,建議收藏
- Linux 實用操作彙總(二)
- AWS 日誌監控 Flow Logs Vs CloudTrail Vs CloudWatch
- AWS 日誌監控 CloudTrail Vs CloudWatch
- 面試反殺 | 請談談Java8-18引入的新特性(六)
- 面試反殺 | 請談談Java8-18引入的新特性(四)
- 面試反殺 | 請談談Java8-18引入的新特性(五)
- 面試反殺 | 請談談Java8-18引入的新特性(三)
- 面試反殺 | 請談談Java8-18引入的新特性(二)
- 面試反殺 | 請談談Java8-18引入的新特性(一)
- 什麼是 gRPC? 它比 REST API 好嗎?
- Spring i18n – 國際化資源解析