Lombok 是一個 Java library,可以透過簡單的寫法自動生成 Java 的 code,像是 setter、getter、logger…等,目的在消除冗長的 code 和提高開發效率
例如當你在 Class 上加上了一個 @Getter
和 @Setter
之後,Lombok 就會自動幫你產生 getter 和 setter 出來,所以你就不用再自己去寫這些煩人的程式啦!
之所以加個 @Getter
就可以幫我們自動生成所有變數的 getter,是因為 Lombok 參與了 Java 在 compile 階段生成 .class
檔的過程,Lombok 會幫我們自動寫一堆 getter,然後塞進 .class
檔,所以真正被編譯出來的 User.class 檔案,是包含完整的 getter 的
所以簡單的說,Lombok 可以算是一種語法糖,只是在幫我們增進開發效率而已,實際上所產生出來的.class
檔仍然是完全正常的!
要在 project 中使用 Lombok,除了要在 maven 中加入 Lombok dependency,還要安裝 Intellij 的 Lombok 插件
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
</dependency>
補充:我使用的 Intellij 版本是 2019.3.3,可能會因為版本差異導致安裝方式有改變
先點選左上角 Intellij IDEA -> Preferences
然後點擊左邊的 Plugins,再點擊上面的 Marketplace tab,然後就可以在搜尋欄中輸入lombok
,並且找到 Lombok 插件並安裝它
其實在 maven 加入 Lombok dependency 之後,使用 mvn clean package
就可以正常 build 過,在 Intellij 中點擊綠色按鈕也可以運行程式
之所以還要特地安裝 Intellij 的 Lombok 插件,是因為如果不安裝 Lombok 插件的話,Intellij 就會沒辦法自動提示出 Lombok 產生的方法,所以就會發生你的 code 一片紅,但是運行卻可以通過的奇妙現象
像是下面這段 code 中,因為對 Intellij 來說,code 裡並不存在 setter,所以沒辦法自動提示 setId()
、setName()
等方法,但是又因為我們在 maven 中有加入 Lombok dependency,所以點擊第 13 行的綠色箭頭運行程式的話,是可以正常運行成功的
所以 Lombok 算是侵入性很高的一個 library,只要團隊中有一個人用 Lombok 開發,那麼所有的人都必須得安裝 Lombok 插件才行,這樣才不會發生在 Intellij 中一打開 project 時,整片都是痛苦的紅字
Lombok 官網提供了許多好用的註解,但是「勁酒雖好,可不能貪杯」,你用了越多 Lombok 的進階用法,會讓整個團隊的學習曲線上升,反而會造成反效果,所以在此處只解釋最常見、並且最重要的註解使用方式,其他較少見的用法就不會涵蓋在此文章中
此篇文章會介紹的 Lombok 方法為:
自動產生 getter/setter
自動 override toString()
方法,會輸出所有變數的值
自動生成 equals(Object other)
和 hashcode()
方法,包括所有的「非靜態變數」和「非 transient 變數」
如果某些變數不想要加進判斷,可以透過 exclude 排除(或是也可以反過來,使用 of 指定只要輸出某些字段)
補充: 為什麼只有一個合在一起的註解 @EqualsAndHashCode
,而不是兩個分開的註解 @Equals
和 @HashCode
?
因為在 Java 中有規定,當兩個 object equals 時,他們的 hashcode 一定要相同,反之,當 hashcode 相同時,object 不一定 equals。所以 equals 和 hashcode 要一起 implement,免得發生違反 Java 規定的情形發生
這三個很像,都是在自動生成該 Class 的 constructor,差別只是在「生成的 constructor 的參數不一樣」而已
@NoArgsConstructor : 生成一個沒有參數的 constructor
@AllArgsConstructor : 生成一個包含所有參數的 constructor
補充: 這裡要注意一個 Java 中的實作重點,當我們沒有指定 constructor 時,Java compiler 會幫我們自動生成一個沒有任何參數的 constructor 給該 Class,但是如果我們自己寫了 constructor 之後,Java 就不會自動幫我們補上那個無參數的 constructor 了!
然而很多地方(像是 Spring Data JPA),都會要求每個 Class 一定要有一個無參數的 constructor,所以你在加上 @AllArgsConstructor
時,一定要記得補上 @NoArgsConstrcutor
,不然就會出現各種意外的報錯,一定要記得!!!
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String name;
}
@RequiredArgsConstructor : 生成一個包含「特定參數」的 constructor,特定參數指的是「那些有加上 final 修飾詞的變數們」
補充一下,如果所有的變數都是正常的(即是都沒有用 final 修飾的話),那就會生成一個沒有任何參數的 constructor
懶人包,只要加了 @Data,等於同時加了以下註解:
@Data 是使用頻率最高的 Lombok 用法,通常 @Data 會加在一個值可以被更新的 Object 上,像是日常使用的 DTO 們、或是 JPA 裡的 Entity 們,就很適合加上 @Data,也就是 @Data for mutable class(@Data for 可變動的 Class)
也是懶人包,但是他會把所有的變數都設成 final,其他的就跟 @Data 一樣,等於同時加了以下註解:
上面那個 @Data 適合用在 POJO 或 DTO 上,而這個 @Value,則是適合加在「值不希望被改變的 Class 上」
所以像是某個 Class 的值當創建後就不希望被更改,只希望我們讀它而已,這時候就適合加上 @Value,也就是 @Value for immutable class(@Value for 不可變動的 Class)
另外在使用 @Value 時也要留意一下,此 Lombok 註解 @Value 和另一個 Spring 的註解 @Value 撞名,在 import 時要小心不要 import 錯
自動生成流式 set 值寫法,從此之後再也不用寫一堆 setter 了!
不過要特別注意,雖然只要在 Class 上加上 @Builder,我們就能夠用流式寫法快速設定 Object 的值,但是還是要記得實作 setter 方法,不能省略(因為 Spring 框架中有很多地方都會用到 Object 的 getter/setter,對他們取值/賦值)
所以在使用上,通常是 @Data 和 @Builder 會一起使用,即是將他們同時加在同個 Class 上,這樣既方便我們流式寫 code,也方便框架做事
@Data
@Builder
public class User {
private Integer id;
private String name;
}
自動生成該 Class 的 log 變數,要打日誌就可以直接打,不用再手動 new 一個 log 變數出來了
除了 @Slf4j 之外,Lombok 也有提供其他日誌框架的註解可以使用,像是 @Log、@Log4j…等等,他們都是用來創建一個 log 變數,只是底層使用的日誌 library 不一樣而已
@Log // 等同於下方 log 語句
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j // 等同於下方 log 語句
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
而因為 Spring Boot 預設使用的日誌框架為 slf4j + logback,所以最常用的註解為 @Slf4j,不需要做什麼額外的設定,直接使用就可以了
這篇文章介紹了 Lombok 中的好用方法,替我們節省了開發 Spring Boot 時所撰寫的冗長的程式
如果你對後端技術有興趣的話,也歡迎免費訂閱 《古古的後端筆記》電子報 ,每週二為你送上一篇後端技術分享