解決lombok 父類和子類builder不兼容的問題
遇到的問題
在寫代碼時,有時因為需要定義一些重復的參數(shù),為了復用之前傳參的DTO,會對原有的類進行繼承,從而達到避免重復代碼的效果。
但是,當父類中使用了lombok的@Builder注解,子類也需要@builder注解時,就會出現(xiàn)異常
排查和解決
由于實際的代碼存在敏感信息,這里分別定義兩個類Parent和Child來進行場景的模擬
@Data
@Builder
class Parent {
? ? private String parentProperty1;
? ? private String parentProperty2;
}
@EqualsAndHashCode(callSuper = true)
@Data
@Builder
class Child extends Parent {
? ? private String childProperty1;
}這時在嘗試使用子類的builder方法時,發(fā)現(xiàn)沒有辦法鏈式調用,使用時只能初始化子類中的變量,編譯時會直接失敗,拋出異常
Error:(160, 1) java: 無法將類 org.example.Parent中的構造器 Parent應用到給定類型;
需要: java.lang.String,java.lang.String
找到: 沒有參數(shù)
原因: 實際參數(shù)列表和形式參數(shù)列表長度不同
這是在編譯子類的@Builder注解時出現(xiàn)的異常,原因直觀的看起來是找不到構造器,在Parent類上加上@NoArgsConstructor和@AllArgsConstructor這兩個注解就能解決這個問題,但是同時會出現(xiàn)新的編譯問題,是什么問題先按下不表。
想要簡單的解決加上@Builder之后就會報錯的問題,那么直接把父類的@Builder這個注解拿掉就行了,不過這時無法設置父類的屬性,如果還想在子類中使用構建器模式來初始化父類的屬性,還有另一種方法,在子類中實現(xiàn)一個能夠初始化父類屬性的構造器,并在這個構造方法上添加@Builder注解。
這時的代碼:
@Data
@NoArgsConstructor
@AllArgsConstructor
class Parent {
? ? private String parentProperty1;
? ? private String parentProperty2;
}
@Data
class Child extends Parent {
? ? private String childProperty1;
? ? @Builder
? ? public Child(String parentProperty1, String parentProperty2, String childProperty1){
? ? ? ? super(parentProperty1, parentProperty2);
? ? ? ? this.childProperty1 = childProperty1;
? ? }
}不過使用這種方法只能解決子類使用@Builder的問題,但是在更多的時候,父類也是需要@Builder這個注解的,那么在這種情況下應該怎么解決呢?
而且這時還會有另一個新的問題出現(xiàn),使用了@Data注解和@Builder注解的子類無法使用無參構造器來創(chuàng)建對象,這時需要在子類上顯式的加上@NoArgsConstructor這個注解才能解決。
如果要更細致的分析,就得從從@Builder的原理說起,了解@Builder到底生成了哪些代碼?
這一步可以自己編譯代碼看看,當然如果自己寫過builder建造者模式的實現(xiàn),應該能想到他是實現(xiàn)了一個名稱以Builder為后綴的靜態(tài)內部類,在調用build()方法的時候調用外部類的全參構造方法來生成外部類的實例。
回到之前的問題,當子類和父類同時存在@Builder注解時,在解決了構造器異常之后,如果編譯代碼,會出現(xiàn)異常:
Error:(164, 5) java: org.example.Child中的builder()無法覆蓋org.example.Parent中的builder()
返回類型org.example.Child.ChildBuilder與org.example.Parent.ParentBuilder不兼容
這里的問題就簡單一些了,父類的builder()方法返回的是ParentBuilder這個靜態(tài)內部類類型的對象,而子類生成的builder()方法返回的是ChildBuilder這個類型的對象。
兩者的名稱重復了,而由于返回類型不兼容而無法按覆蓋。
根據(jù)@Builder注解的源碼可以發(fā)現(xiàn)名稱是可以自定義的,于是可以通過給子類builder方法自定義名稱的方式來解決這個問題。
最終的代碼:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
class Parent {
? ? private String parentProperty1;
? ? private String parentProperty2;
}
@Data
class Child extends Parent {
? ? private String childProperty1;
? ? @Builder(builderMethodName = "childBuilder")
? ? public Child(String parentProperty1, String parentProperty2, String childProperty1){
? ? ? ? super(parentProperty1, parentProperty2);
? ? ? ? this.childProperty1 = childProperty1;
? ? }
}結尾
值得一提的是,1.8.2之后版本的lombok提供了一個新的注解@SuperBuilder來解決這個問題,不過我沒有用過,而且從網(wǎng)上搜索出來的結果來看,還是存在一些問題的,建議謹慎升級。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
SpringMVC實現(xiàn)Controller的三種方式總結
這篇文章主要介紹了SpringMVC實現(xiàn)Controller的三種方式總結,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
SpringCloud?Gateway中GatewayFilterChain執(zhí)行流程詳解
Spring?Cloud?Gateway旨在為微服務架構提供一種簡單有效的、統(tǒng)一的?API?路由管理方式。Spring?Cloud?Gateway?作為?Spring?Cloud?生態(tài)系中的網(wǎng)關,它不僅提供統(tǒng)一的路由方式,并且基于?Filter?鏈的方式提供了網(wǎng)關基本的功能,例如:安全、監(jiān)控/埋點和限流等2022-10-10
springboot中PostMapping正常接收json參數(shù)后返回404問題
這篇文章主要介紹了springboot中PostMapping正常接收json參數(shù)后返回404問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-05-05

