相信但凡有一點Java編程經歷的人,都見過或者寫過下面這種代碼。這是一個簡單的POJO,只有4個fields,加上構造器、equals
、hash
、toString
以及各種getter setter
,前前后后加起來大約70多行代碼。這還只是4個fields,如果有十個以上,那么代碼行數輕輕松松過一百。如果老板或主顧們按代碼行數給錢的話,Java程序員應該都發財了。
public class Mountain {
private String name;
private double latitude, longitude;
private String country;
public Mountain(String name, double latitude, double longitude, String country) {
//...巴拉巴拉
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Mountain mountain = (Mountain) o;
return Double.compare(mountain.latitude, latitude) == 0 &&
Double.compare(mountain.longitude, longitude) == 0 &&
Objects.equals(name, mountain.name) && Objects.equals(country, mountain.country);
}
//各種getter setter toString hashCode...etc
}
有了代碼自動生成,這種苦痛會稍微降低點,但是你的代碼仍然會顯得“臟亂”。Project Lombok,一個成熟的library,通過編譯期插入的方式,大量減少樣板代碼,讓你的代碼顯得干凈、簡潔、易讀。相信很多人都用上了,沒用的,建議趕緊上車。
安裝
在Maven的pom文件中加入
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
即可安裝成功。你也可以到官網下載jar包,通過IDE直接導入,但是不推薦。竊以為,連前端都少不了npm的年代,Maven和Gradle至少二選一。
另外,譬如IntelliJ Idea
這種IDE,需要在plugin market
里搜索lombok
,下載並安裝相關插件,否則IDE會報錯。
使用注解簡化代碼
這里主要介紹一些常用注解。
剪除getter、setter樣板代碼
@Setter @Getter @EqualsAndHashCode @ToString(exclude = {"country"})
public class Mountain {
private String name;
private double latitude, longitude;
private String country;
}
注解的名稱幾乎都是自解釋的。
@Setter
、@Getter
可以生成全部非靜態field的getter和setter方法,@EqualsAndHashCode
可以生成標准的equals()
和hashCode()
方法。@ToString
,顧名思義,生成toString()
方法,其中exclude
屬性用於排除不想出現在返回值中的field。
從圖中也可以看出,各種getter
、equals
等方法,已經在編譯期生成了。
另外@Setter
、@Getter
也可以注解到filed上,對於某些field,我們只想提供getter
方法,直接注解field的方式更加靈活。
空值檢查——@NonNull
@Setter @Getter @NonNull
public class Mountain {
private String name;
private double latitude, longitude;
private String country;
}
通過@NonNull
注解,可以自動檢查setter
方法的入參是否非空,當傳入null
值時,則拋出空指針異常。它等同於以下實現,
public id setName(@NonNull final String name){
if(name == null) throw
new java.lang.NullPointerException("name");
this.name = name;
}
生成構造器
@NoArgsConstructor @AllArgsConstructor
public class Mountain {
private String name;
private double latitude, longitude;
private String country;
}
使用@NoArgsConstructor
可以生成空參構造器,就像編譯器平日為我們做的一樣。@AllArgsConstructor
可以生成包含全部非靜態field的構造器。
融合多個注解——@Data
以上一個一個注解的添加上去,仍然非常的繁瑣,有沒有一鍵搞定的注解?
@Data @AllArgsConstructor
public class Mountain {
private String name;
private double latitude, longitude;
private String country;
}
@Data
,相當於@ToString
+ @EqualsAndHashCode
+@Getter
+@Setter
+@RequiredArgsConstructor
。配合@AllArgsConstructor
幾乎能覆蓋日常大部分需求。
另外,@Data
還有一個親兄弟——@value
,功能幾乎等同於@Data
+@AllArgsConstructor
,不同的是,它生成的是不可變類(Immutable class)。在class
關鍵字前會自動加上final
修飾符,且不再提供各個field
的setter
參數。
生成構造器——@Build
@Builder
public class Mountain {
private String name;
private double latitude, longitude;
private String country;
@Build
注解可以提供給當前對象一個構造器。不知道有咩有童鞋有過這樣的經歷,為了提供不同field組合的初始化構造器,結果必須寫一大堆構造器重載方法。如果有10+的filed的話,僅僅構造器就有100行代碼。對於這種情況,《Effetive Java》的作者建議,我們應該提供一個構造器,而不是重載一堆讓人眼花繚亂的構造器。現在,我們僅僅添加一個@Build
,就可以做到大神提供的最佳實踐。
其調用起來也非常簡單:
Mountain.builder()
.name("tai")
.country("china").latitude(22.456).build();
這樣看起來是不是更加的舒服、簡潔呢!
結語以及其他
另外還有@Cleanup
注解,它相當於try-with-resource的另一個版本,避免手動調用各種丑陋的close()
方法。在Java7之前這是很好用的,現在也可以作為你的備選項。
@Synchronized
,用於標注靜態方法,相當於原生的syncronize
關鍵字。
@Log4j2
配合apache的log4j2庫使用,注解在class級別上
@Log4j
public class TestModel {
public void hello(){
log.info("log....");
}
}
以上都是一些常用的注解,他們可以消除我們日常大部分的POJO樣板代碼,使代碼保持簡潔、易讀,更多特性和注解可以參考官方文檔。