Lombok使用詳解
在以往的Java編程中,每當創建一個對象類後,我們都要手動寫Getter/Setter、構造器方法、字符串輸出的ToString方法和Equals/HashCode方法等,非常繁瑣,代碼可讀性也很差。現在,我給大家推薦一款高效插件–lombok,讓編程變得更加高效快捷。
Lombok簡介
Lombak是一款Java開發插件,它主要應用在Java模型對象類中。
Lomabk通過註解的方式,隱式(即代碼中不可見,但編譯後可見)實現Getter/Setter、構造器方法、字符串輸出的ToString方法和Equals/HashCode方法等,大幅度精簡冗長繁瑣的代碼。
Lombok針對這些內容的處理是在編譯期,而不是通過反射機制,這樣的好處是並不會降低系統的性能。
lombok的官方地址:https://projectlombok.org/
lombok的Github地址:https://github.com/rzwitserloot/lombok
lombok的maven地址:https://mvnrepository.com/artifact/org.projectlombok/lombok
Lombok安裝
Lombok的安裝分兩部分:Idea插件的安裝和maven中pom文件的導入。
第一步,在IDEA中安裝插件:File–Settings…–搜索plugins–搜索lombok,點擊INSTALL即可。
第二步,引入pom中依賴:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
Lombak使用
@Data
@Data最常用的註解之一。註解在類上,提供該類所有屬性的getter/setter方法,還提供了equals、canEqual、hashCode、toString方法。
效果如何,請看下面示例。
@Data
public class Demo {
private int id;
private String name;
}
上面一段非常簡潔的代碼,編譯後是什麼樣子呢?
public class Demo {
private int id;
private String name;
public Demo() {
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
public void setId(final int id) {
this.id = id;
}
public void setName(final String name) {
this.name = name;
}
public boolean equals(final Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Demo)) {
return false;
} else {
Demo other = (Demo) o;
if (!other.canEqual(this)) {
return false;
} else if (this.getId() != other.getId()) {
return false;
} else {
Object this$name = this.getName();
Object other$name = other.getName();
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$remark.equals(other$remark)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(final Object other) {
return other instanceof Demo;
}
public int hashCode() {
int PRIME = true;
int result = 1;
int result = result * 59 + this.getId();
Object $remark = this.getRemark();
result = result * 59 + ($remark == null ? 43 : $remark.hashCode());
return result;
}
public String toString() {
return "Demo(id=" + this.getId() + ", remark=" + this.getRemark() + ")";
}
}
可見,lombak的@Data註解給對象類提供了默認的構造方法、屬性的getter/setter方法、equals、canEqual、hashCode、toString方法。
更方便的是,當新增屬性或減少屬性時,直接刪除屬性定義即可,效率是否提升了很多?
@Setter&@Getter
@Setter和@Getter都能提供默認的構造方法,根據註解的位置,作用有所不同,以@Setter爲例。
作用於屬性上,爲該屬性提供setter方法:
public class Demo {
private int id;
@Setter
private String name;
}
作用於類上,爲該類所有的屬性提供setter方法:
@Setter
public class Demo {
private int id;
private String name;
}
@Getter與@Setter同理,兩者也可以同時使用。
@Builder
@Builder註釋爲你的類生成相對略微複雜的構建器API。@Builder可以讓你以下面顯示的那樣調用你的代碼,來初始化你的實例對象:
import lombok.Builder;
@Builder
public class Demo {
private int id;
private String name;
}
class Test {
public void test() {
Demo.builder().id(1).name("xiaoming").build();
}
}
@NonNull
作用於屬性上,提供關於此參數的非空檢查,如果參數爲空,則拋出空指針異常。下面做一個對比。
使用lombok:
import lombok.NonNull;
public class NonNullExample extends Something {
private String name;
public NonNullExample(@NonNull Person person) {
super("Hello");
this.name = person.getName();
}
不使用lombok:
public class NonNullExample extends Something {
private String name;
public NonNullExample(@NonNull Person person) {
super("Hello");
if (person == null) {
throw new NullPointerException("person");
}
this.name = person.getName();
}
}
@Log4j
作用於類上,爲該類提供一個屬性名爲log的log4j日誌對象。
@Log4j
public class Demo {
}
該屬性一般使用於Controller、Service等業務處理類上。與此註解相同的還有@Log4j2,顧名思義,針對Log4j2。
@AllArgsConstructor
作用於類上,爲該類提供一個包含全部參的構造方法,注意此時默認構造方法不會提供。
@AllArgsConstructor
public class Demo {
private int id;
private String name;
}
效果如下:
public class Demo {
private int id;
private String name;
public Demo(final int id, final String name) {
this.id = id;
this.name = name;
}
}
@NoArgsConstructor
作用於類上,提供一個無參的構造方法。可以和@AllArgsConstructor同時使用,此時會生成兩個構造方法:無參構造方法和全參構造方法。
@EqualsAndHashCode
作用於類上,生成equals、canEqual、hashCode方法。具體效果參看最開始的@Data效果。
@RequiredArgsConstructor
作用於類上,由類中所有帶有@NonNull註解或者帶有final修飾的成員變量作爲參數生成構造方法。
@Cleanup
作用於變量,保證該變量代表的資源會被自動關閉,默認調用資源的close()方法,如果該資源有其它關閉方法,可使用@Cleanup(“methodName”)來指定。
public void jedisExample(String[] args) {
try {
@Cleanup Jedis jedis = redisService.getJedis();
} catch (Exception ex) {
logger.error(“Jedis異常:”,ex)
}
}
效果相當於:
public void jedisExample(String[] args) {
Jedis jedis= null;
try {
jedis = redisService.getJedis();
} catch (Exception e) {
logger.error(“Jedis異常:”,ex)
} finally {
if (jedis != null) {
try {
jedis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@ToString
作用於類上,生成包含所有參數的toString方法。見@Data中toString方法。
@Value
作用於類上,會生成全參數的構造方法、getter方法、equals、hashCode、toString方法。與@Data相比多了全參構造方法,少了默認構造方法、setter方法和canEqual方法。
該註解需要注意的是:會將字段添加上final修飾,個人感覺此處有些失控,不太建議使用。
@SneakyThrows
作用於方法上,相當於把方法內的代碼添加了一個try-catch處理,捕獲異常catch中用Lombok.sneakyThrow(e)拋出異常。使用@SneakyThrows(BizException.class)指定拋出具體異常。
@SneakyThrows
public int getValue(){
int a = 1;
int b = 0;
return a/b;
}
效果如下:
public int getValue() {
try {
int a = 1;
int b = 0;
return a / b;
} catch (Throwable var3) {
throw var3;
}
}
@Synchronized
作用於類方法或實例方法上,效果與synchronized相同。區別在於鎖對象不同,對於類方法和實例方法,synchronized關鍵字的鎖對象分別是類的class對象和this對象,而@Synchronized的鎖對象分別是私有靜態final對象lock和私有final對象lock。也可以指定鎖對象。
public class FooExample {
private final Object readLock = new Object();
@Synchronized
public static void hello() {
System.out.println("world");
}
@Synchronized("readLock")
public void foo() {
System.out.println("bar");
}
}
效果相當於:
public class FooExample {
private static final Object $LOCK = new Object[0];
private final Object readLock = new Object();
public static void hello() {
synchronized ($LOCK) {
System.out.println("world");
}
}
public void foo() {
synchronized (readLock) {
System.out.println("bar");
}
}
}
val
使用val作爲局部變量聲明的類型,而不是實際寫入類型。執行此操作時,將從初始化表達式推斷出類型。
public Map<String, String> getMap() {
val map = new HashMap<String, String>();
map.put("1", "a");
return map;
}
效果相當於:
public Map<String, String> getMap() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("1", "a");
return map;
}
也就是說在局部變量中,Lombok幫你推斷出具體的類型,但只能用於局部變量中。