在撰寫 Java 時, 常常會遇到一些看似很冗的程式碼, 但又不得不寫, 此時 Lombok 就派上用場了
使用時只需要在 pom.xml 裡面簡單地引入依賴即可
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<scope>provided</scope>
</dependency>
</dependencies>大家想必對以下的程式碼不陌生, 在撰寫類似 DTO, DAO 的類別時, 常常需要實作屬性的 Getter 與 Setter
public class Person {
private String name;
private String job;
public String getName() {
return this.name;
}
void setName(String name) {
this.name = name;
}
public String getJob() {
return this.job;
}
void setJob(String job) {
this.job = job;
}
}只要在屬性上加上 @Getter/@Setter 的標記以後, Lombok 就會在編譯時自動將上述的程式碼產生出來
public class Person {
@Getter @Setter private String name;
@Getter @Setter private String job;
}我們也可以在 @Getter/@Setter 設定存取權限, 如果我們今天想讓某個屬性只被繼承這個父類別的子類別存取, 可以像這樣寫
public class Person {
@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PROTECTED)
private String name;
}這樣就會產生對應層級的 Getter & Setter
public class Person {
private String name;
private String job;
protected String getName() {
return this.name;
}
protected void setName(String name) {
this.name = name;
}
protected String getJob() {
return this.job;
}
protected void setJob(String job) {
this.job = job;
}能使用的 AccessLevel 有以下幾種
- PUBLIC
- PROTECTED
- PACKAGE
- PRIVATE
- NONE
:::info
我們也可以利用 @Data 的標記, 這樣在編譯時就會自動把每個屬性的 Getter, Setter 都產生出來
@Data
public class Person {
private String name;
private String job;
}但如果我們今天想用 @Data 將所有屬性的 Getter & Setter 都產生出來, 但某幾個特定的屬性不想產生時,
就可以利用上面有提到的 AccessLevel 來達成
@Data
public class Person {
private String name;
private String job;
@Setter(AccessLevel.NONE)
@Getter(AccessLevel.NONE)
private String phoneNumber;
}:::
有時候我們的類別內有過多的屬性, 在建構時就會降低程式碼的易讀性
public class Person {
private String firstName;
private String secondName;
private String phoneNumber;
public Person(String firstName, String secondName, String phoneNumber) {
this.firstName = firstName;
this.secondName = secondName;
this.phoneNumber = phoneNumber;
}
}在使用時我們就沒辦法一眼看出填入的變數是代表什麼屬性
Person sean = new Person("Sean", "Chang", "0912345678")如果是使用 Builder 來建構我們的實例的話, 會長得類似下面這樣
PersonBuilder seanBuilder = new Person.builder();
Person sean = seanBuilder
.firstName("Sean")
.secondName("Chang")
.phoneNumber("0912345678")
.build()這樣就能一目瞭然每個變數代表的值了, 不用再回去翻閱類別的程式碼是怎麼實作的
但 Builder 實作起來是非常麻煩的
public class Person {
private String firstName;
private String secondName;
private String phoneNumber;
public PersonBuilder builder() {
return new PersonBuilder();
}
public static class PersonBuilder {
private String firstName;
private String secondName;
private String phoneNumber;
public PersonBuilder firstName(String firstName) {
this.firstName = firstName;
return this;
}
public PersonBuilder secondName(String secondName) {
this.secondName = secondName;
return this;
}
public PersonBuilder phoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
return this;
}
public PersonBuilder build() {
return new Person(firstName, secondName, phoneNumber);
}
}
}但只要使用 Lombok 的 @Builder 標註, 就能在編譯時生成同樣的程式碼
@Builder
public class Person {
private String firstName;
private String secondName;
private String phoneNumber;
}如果今天我們的類別裡面有 Map 或是 List 的型別, 想用 Builder Pattern 來達成疊加的效果
我們可以在屬性前面加上 @Singular 的標註
@Builder
public class Person {
private String firstName;
private String secondName;
private String phoneNumber;
@Singular private List<String> petNames;
}在使用的時候我們就能用類似蓋房子的方式把變數疊加到 List 或是 Map 裡面,
@Builder 會在類別內生成單數的方法,
舉例來說 private List<String> petNames 就會生成 .petName(petName) 的方法
List<String> petNames = List.of("Amy", "Ben");
Person.PersonBuilder personBuilder = Person.builder();
personBuilder
.firstName("Sean")
.secondName("Chang")
.phoneNumber("0912345678");
// 效果等同於 personBuilder.petNames(petNames)
for (String petName : petNames) {
personBuilder.petName(petName);
}
Person person = personBuilder.build();如果是 Map 的型別
@Builder
public class Person {
private String firstName;
private String secondName;
private String phoneNumber;
@Singular private Map<String, Integer> accounts;
}使用起來則會像這樣
Person.PersonBuilder builder = Person.builder();
builder
.firstName("Sean")
.secondName("Chang")
.phoneNumber("0912345678")
.account("Cathay", 10000)
.account("E-Sun", 5000);使用了 Lombok 以後, 以往非常好用但實作非常麻煩的 Builder Pattern 也變得非常容易上手