騰訊電商二面:Lombok 是銀彈?還是陷阱?
在 Java語言中,有大量類似于 getter、setter、toString 這樣的模板代碼,為了解決這個問題,一個流行的框架 Lombok誕生了。前幾天看到騰訊的一道 2面題:Lombok是銀彈?還是陷阱?生產(chǎn)環(huán)境建議使用 Lombok嗎?今天我們一起來聊一聊。
Lombok是什么?
Lombok是一個三方開源的 Java庫,通過注解可以自動將代碼插入到編輯器和構(gòu)建工具中,為 Java程序員省略了很多樣板代碼的編寫,除了生成getter、setter方法,還可以生成 equals、hashCode和各種類構(gòu)造函數(shù)等。在很多 Java程序員的眼中簡直就是銀彈。
Lombok如何使用?
Lombok的使用很簡單,主要是通過注解來精簡代碼,常用的注解如下:
- @Getter:作用在類上,為實體類所有屬性添加 getter方法;
- @Setter:作用在類上,為實體類所有屬性添加 setter方法;
- @ToString:作用在類上,當(dāng)調(diào)用toString()方法,可以輸出實體類中所有屬性的值。
- @Data:作用在類上,相當(dāng)于同時使用了@ToString、@EqualsAndHashCode、@Getter、@Setter和@RequiredArgsConstrutor這些注解;
- @AllArgsConstructor:作用在類上,為實體類生成包含所有屬性參數(shù)的構(gòu)造方法;
- @NoArgsConstructor:作用在類上,為實體類生成無參構(gòu)造方法;
- @RequiredArgsConstructor:作用在類上,配合@NonNull注解使用,生成指定參數(shù)的構(gòu)造方法。比如在age屬性前面加@NonNull注解,則User生成需要age參數(shù)的構(gòu)造方法;
下面給出了一個 Lombok @Data注解的使用示例:
import lombok.Data;
@Data
public class User {
private String id;
private String name;
}
上述示例通過在類上使用 @Data注解后,我們就不需要再手動添加 getter、setter等模版代碼,整個代碼看起來簡潔了很多。
Lombok如何工作?
從 Lombok如何使用的講解中我們可以看到:Lombok主要是依賴注解來標識(標記)需要在該類中生成哪些代碼。除此之外,還有一個重要的技術(shù)點是抽象語法樹(AST)。
抽象語法樹(AST,Abstract Syntax Tree)是一種用于表示程序源代碼結(jié)構(gòu)的樹狀數(shù)據(jù)結(jié)構(gòu)。它抽象出代碼的語法結(jié)構(gòu),忽略某些細節(jié),以便于編譯器或解釋器進行分析和處理。
在 Java中,AST是一種在生成字節(jié)碼之前創(chuàng)建的中間結(jié)構(gòu),如下圖為 AST示例:
Lombok是注解和 AST的完美組合,Lombok通過識別注解,然后操縱 AST將不存在的樣板代碼插入到類中。
但是 Lombok并不是直接修改源代碼文件,而是在編譯過程中動態(tài)生成代碼,為了實現(xiàn)這一點,Lombok需要攔截 Java編譯器的調(diào)用,而這種攔截是通過插件來實現(xiàn)的,比如 IntelliJ, VSCode, Eclipse 或者在構(gòu)建工具 Maven, Gradle, Make等。因此,如果選用的 IDE或依賴/構(gòu)建管理器不支持 Lombok,代碼將無法編譯。
考慮因素
Lombok為 Java省略了很多樣板代碼的編寫,但是,對于項目中使用 Lombok,我們還是應(yīng)該多一些思考,這里主要總結(jié)為下面 4個考慮點:
1.編譯時間
由于 Lombok在編譯時完成樣板代碼的填充,因此,勢必導(dǎo)致編譯時間的增加,尤其是在大型代碼庫中,這種增加可能會有很大影響,盡管 Lombok隨著版本的升級,性能也在提升,但使用 Lombok的時間仍然比不使用 Lombok的時間長。
2.友好性
Lombok大大減少了Java類中的樣板代碼,特別是在領(lǐng)域類(TOs、DTOs、實體)中,這些類通常有很多類級別的屬性。
但是,使用 Lombok后,所有參與這個項目開發(fā)的技術(shù)人員都需要安裝 Lombok插件,因此,對于不愿意使用 Lombok的開發(fā)人員來說不太友好。另外,如果團隊中有剛工作的組員,如果一開始就在 Lombok這種環(huán)境下,那么對于他們的成長也是不友好的。
3.Java標準
在開發(fā)過程中,我們通常會使用 IDE或構(gòu)建工具自動編譯Java代碼,所以 Lombok可以在這個階段自動完成它的工作,但是,假如我們只是使用 javac來編譯源代碼,如果源代碼中使用了 Lombok生成的get方法,這種情況下編譯會出錯提示get方法不存在。
4.兼容性
如果項目中涉及 JDK的版本升級,可能出現(xiàn)兼容性問題,因為每個版本可能會改變 AST的生成和解釋方式。因此,如果使用了 Lombok,在升級 Java版本后,可能會導(dǎo)致項目無法編譯。
盡管這個問題重新編譯后可以解決,但是,如果使用了 Lombok,還是要注意上述提到的可能編譯失敗的問題。
5.開發(fā)和CR
Lombok 是在編譯期為類生成樣板代碼,因此,開發(fā)人員在調(diào)試時看不到這些代碼,可能會給調(diào)試帶來一些困難,另外,Lombok 自動生成的代碼是隱式的,可能會讓代碼行為不夠透明,給代碼審查和維護帶來一些挑戰(zhàn)。
總結(jié)
本文從面試題出發(fā),講解了 Lombok的工作原理以及其優(yōu)點和需要考慮的因素:
1.優(yōu)點
可以大大減少樣板代碼的手動編寫
2.考慮因素
- 編譯時間
- 友好性
- Java標準
- 兼容性
- 開發(fā)和CR
3.個人建議
對于我個人而言,傾向于在項目不使用 Lombok,主要有以下 3個原因:
- Lombok只是減少樣板代碼,幫助程序員偷了懶,并沒有給項目帶來什么實質(zhì)性的收益,而且這些樣板代碼 IDE也可以快速生成;
- 基于上述 5個考慮因素的任何一個,引入 Lombok都不是一個很好的決定;
- 網(wǎng)上看到了 Lombok很多花哨的使用方式,這樣潛在的風(fēng)險更大;
最后,項目中是否使用 Lombok,取決于個人喜好以及團隊和項目的選擇(大廠一般都會禁用 Lombok),但是,上述的考慮因素或許可以給你的決策多一個參考。