前言
what环壤?你的 Java 代碼中還充斥著大量的 set/get 方法?
我們在剛開始學習 Java 語言的時候講過钞诡,面向?qū)ο蟮娜筇卣骶褪欠庋b郑现,繼承,和多態(tài)臭增。在 Java 中懂酱,要保證封裝性,需要將成員變量私有化誊抛,對外提供 set/get 方法來訪問列牺,雖然現(xiàn)在的 IDE,像 eclipse拗窃,IDEA都提供了快捷鍵瞎领,來生成 set/get 方法泌辫,但是在做項目的時候,一個 JavaBean 往往會有很多的成員變量九默,一個變量對應(yīng)兩個方法震放,如果有10幾個成員變量,那么會對應(yīng)20多個方法驼修,也許還要去寫構(gòu)造器殿遂、equals 等方法,而且需要維護乙各。這樣一來墨礁,會使代碼變得非常冗余,這些顯得很冗長也沒有太多技術(shù)含量耳峦,一旦修改屬性恩静,就容易出現(xiàn)忘記修改對應(yīng)方法的失誤。
我在看大佬的項目的源碼的時候蹲坷,看到他們的代碼中都沒有 set/get 方法驶乾,取而代之的是在 JavaBean 上標注的注解,我感到非常的好奇循签,原來他們是用了一種叫做 Lombok 的插件级乐,便去詳細了解了這個插件。
Lombok背景介紹
官方介紹如下:
Project Lombok makes java a spicier language by adding 'handlers' that know how to build and compile simple, boilerplate-free, not-quite-java code.
大致意思是 Lombok 通過增加一些“處理程序”懦底,可以讓 Java 變得簡潔唇牧、快速。
Lombok使用方法
Lombok 能通過注解的方式聚唐,在編譯時自動為屬性生成構(gòu)造器丐重、getter/setter、equals杆查、hashcode扮惦、toString 方法。出現(xiàn)的神奇就是在源碼中沒有 getter 和 setter 方法亲桦,但是在編譯生成的字節(jié)碼文件中有 getter 和 setter 方法崖蜜。這樣就省去了手動重建這些代碼的麻煩,使代碼看起來更簡潔些客峭。
Lombok 的使用跟引用 jar 包一樣豫领,可以在官網(wǎng)(https://projectlombok.org/download)下載 jar 包,也可以使用 maven 添加依賴:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
注意:
第一次使用 Lombok 插件需要做如下幾步配置
- 將 Lombok 插件安裝到 IDEA
file -> setting
選中 Plugins舔琅,搜索 Lombok等恐,點擊 Install
選擇默認的編譯方式為 javac,因為 eclipse 是不支持 Lombok 的編譯方式的,javac 支持 Lombok 的編譯方式课蔬。
打開注解生成器 Enable annotation processing
再次注意:
IntelliJ IDEA 2019.2(也就是我用的版本)默認是不支持 Lombok 插件的囱稽,需要去
https://plugins.jetbrains.com/plugin/6317-lombok/versions
下載對應(yīng)版本的插件,然后手動引入二跋,在 IDEA 中選擇 File -> Setting -> plugins 找到 Install Plugin from Disk…(注意版本不同位置可能有所差異)
接下來我們來分析 Lombok 中注解的具體用法
@Data
@Data 注解在類上战惊,會為類的所有屬性自動生成 setter/getter、equals扎即、canEqual吞获、hashCode、toString 方法谚鄙,如為 final 屬性衫哥,則不會為該屬性生成 setter 方法。
比如我們寫一個學生類
@Data
public class Student {
private String name;
private Integer age;
private Integer id;
private String major;
}
這樣就可以調(diào)用 set/get 方法了襟锐。
@Getter/@Setter
如果覺得@Data 太過殘暴(因為@Data 集合了@ToString、@EqualsAndHashCode膛锭、@Getter/@Setter粮坞、@RequiredArgsConstructor 的所有特性)不夠精細,可以使用@Getter/@Setter 注解初狰,此注解在屬性上莫杈,可以為相應(yīng)的屬性自動生成 set/get 方法。
public class Student {
@Setter private String name;
private Integer age;
private Integer id;
private String major;
public static void main(String[] args) {
Student stu = new Student();
stu.setName("Mr.ml");
}
}
@NonNull
該注解用在屬性或構(gòu)造器上奢入,Lombok 會生成一個非空的聲明筝闹,可用于校驗參數(shù),能幫助避免空指針腥光。
public class Student {
@Setter private String name;
private Integer age;
private Integer id;
private String major;
public Student(@NonNull String name) {
this.name = name;
}
}
@Cleanup
該注解能幫助我們自動調(diào)用 close() 方法关顷,很大的簡化了代碼。
public class CleanupExample {
public static void main(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
}
@EqualsAndHashCode
默認情況下武福,會使用所有非靜態(tài)(non-static)和非瞬態(tài)(non-transient)屬性來生成 equals 和 hashCode议双,也能通過 exclude 注解來排除一些屬性。
@EqualsAndHashCode(exclude={"id", "shape"})
public class EqualsAndHashCodeExample {
private transient int transientVar = 10;
private String name;
private double score;
private Shape shape = new Square(5, 10);
private String[] tags;
private int id;
public String getName() {
return this.name;
}
@EqualsAndHashCode(callSuper=true)
public static class Square extends Shape {
private final int width, height;
public Square(int width, int height) {
this.width = width;
this.height = height;
}
}
}
@ToString
類使用@ToString 注解捉片,Lombok 會生成一個 toString() 方法平痰,默認情況下,會輸出類名伍纫、所有屬性(會按照屬性定義順序)宗雇,用逗號來分割。
通過將 includeFieldNames 參數(shù)設(shè)為 true莹规,就能明確的輸出 toString() 屬性赔蒲。這一點是不是有點繞口,通過代碼來看會更清晰些。
@ToString(exclude="id")
public class ToStringExample {
private static final int STATIC_VAR = 10;
private String name;
private Shape shape = new Square(5, 10);
private String[] tags;
private int id;
public String getName() {
return this.getName();
}
@ToString(callSuper=true, includeFieldNames=true)
public static class Square extends Shape {
private final int width, height;
public Square(int width, int height) {
this.width = width;
this.height = height;
}
}
}
@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
無參構(gòu)造器嘹履、部分參數(shù)構(gòu)造器腻扇、全參構(gòu)造器。Lombok沒法實現(xiàn)多種參數(shù)構(gòu)造器的重載砾嫉。
@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class ConstructorExample<T> {
private int x, y;
@NonNull private T description;
@NoArgsConstructor
public static class NoArgsExample {
@NonNull private String field;
}
}