史上最全面的 Lombok 注解介紹,Look 一下吧!


一、@Getter and @Setter
使用@Getter和/或@Setter注釋任何字段,以使lombok自動生成默認的getter / setter。
默認的getter只是返回該字段,如果該字段被稱為foo,則名為getFoo(如果該字段的類型為boolean,則為isFoo)。
默認生成的 getter / setter方法是公共的,除非你明確指定一個AccessLevel。合法訪問級別為PUBLIC,PROTECTED,PACKAGE和PRIVATE。
你還可以在類上添加@Getter和/或@Setter注釋。在這種情況下,就好像你使用該注釋來注釋該類中的所有非靜態字段一樣。
你始終可以使用特殊的AccessLevel.NONE訪問級別來手動禁用任何字段的getter / setter生成。這使你可以覆蓋類上的@Getter,@Setter或@Data注釋的行為。
With Lombok:
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;

public class GetterSetterExample {

@Getter
@Setter
private int age = 10;

@Setter(AccessLevel.PROTECTED)
private String name;

@Override
public String toString() {
return String.format("%s (age: %d)", name, age);
}
}
Native Java:
public class GetterSetterExample {

private int age = 10;

private String name;

@Override
public String toString() {
return String.format("%s (age: %d)", name, age);
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

protected void setName(String name) {
this.name = name;
}
}
二、@ToString
任何類定義都可以使用@ToString注釋,以使lombok生成toString()方法的實現。
默認情況下,將打印所有非靜態字段。如果要跳過某些字段,可以使用@ ToString.Exclude注釋這些字段。或者,可以通過使用@ToString(onlyExplicitlyIncluded = true),然后使用@ToString.Include標記要包含的每個字段,來確切指定希望使用的字段。
通過將callSuper設置為true,可以將toString的超類實現的輸出包含到輸出中。請注意,java.lang.Object中toString() 的默認實現幾乎毫無意義。
With Lombok:
import lombok.ToString;

@ToString
public class ToStringExample {
private static final int STATIC_VAR = 10;
private String name;
private Shape shape = new Square(5, 10);
private String[] tags;
@ToString.Exclude
private int id;

public String getName() {
return this.name;
}

@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;
}

}
}
Native Java:
import java.util.Arrays;

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.name;
}

public static class Square extends Shape {
private final int width, height;

public Square(int width, int height) {
  this.width = width;
  this.height = height;
}

@Override 
public String toString() {
  return "Square(super=" + super.toString() + ", width=" + this.width + ", height=" + this.height + ")";
}

}

@Override
public String toString() {
return "ToStringExample(" + this.getName() + ", " + this.shape + ", " + Arrays.deepToString(this.tags) + ")";
}
}
三、@EqualsAndHashCode
任何類定義都可以使用@EqualsAndHashCode進行注釋,以使lombok生成equals(Object other)和hashCode()方法的實現。默認情況下,它將使用所有非靜態,非瞬態字段,但是您可以通過使用@EqualsAndHashCode.Include標記類型成員來修改使用哪些字段(甚至指定要使用各種方法的輸出)。 @EqualsAndHashCode.Exclude。或者,可以通過使用@ EqualsAndHashCode.Include標記並使用@EqualsAndHashCode(onlyExplicitlyIncluded = true)來精確指定要使用的字段或方法。
如果將@EqualsAndHashCode應用於擴展另一個類的類,則此功能會有些棘手。通常,為此類自動生成equals和hashCode方法是一個壞主意,因為超類還定義了字段,該字段也需要equals / hashCode代碼,但不會生成此代碼。通過將callSuper設置為true,可以在生成的方法中包括超類的equals和hashCode方法。
With Lombok:
import lombok.EqualsAndHashCode;

@EqualsAndHashCode
public class EqualsAndHashCodeExample {
private transient int transientVar = 10;
private String name;
private double score;
@EqualsAndHashCode.Exclude
private Shape shape = new Square(5, 10);
private String[] tags;
@EqualsAndHashCode.Exclude
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;
}

}
}
Native Java:
import java.util.Arrays;

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;
}

@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCodeExample)) return false;
EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o;
if (!other.canEqual((Object)this)) return false;
if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
if (Double.compare(this.score, other.score) != 0) return false;
if (!Arrays.deepEquals(this.tags, other.tags)) return false;
return true;
}

@Override
public int hashCode() {
final int PRIME = 59;
int result = 1;
final long temp1 = Double.doubleToLongBits(this.score);
result = (resultPRIME) + (this.name == null ? 43 : this.name.hashCode());
result = (result
PRIME) + (int)(temp1 ^ (temp1 >>> 32));
result = (result*PRIME) + Arrays.deepHashCode(this.tags);
return result;
}

protected boolean canEqual(Object other) {
return other instanceof EqualsAndHashCodeExample;
}

public static class Square extends Shape {
private final int width, height;

public Square(int width, int height) {
  this.width = width;
  this.height = height;
}

@Override 
public boolean equals(Object o) {
  if (o == this) return true;
  if (!(o instanceof Square)) return false;
  Square other = (Square) o;
  if (!other.canEqual((Object)this)) return false;
  if (!super.equals(o)) return false;
  if (this.width != other.width) return false;
  if (this.height != other.height) return false;
  return true;
}

@Override 
public int hashCode() {
  final int PRIME = 59;
  int result = 1;
  result = (result*PRIME) + super.hashCode();
  result = (result*PRIME) + this.width;
  result = (result*PRIME) + this.height;
  return result;
}

protected boolean canEqual(Object other) {
  return other instanceof Square;
}

}
}
四、@AllArgsConstructor
@RequiredArgsConstructor
@NoArgsConstructor
@NoArgsConstructor將生成沒有參數的構造函數。如果字段由final修飾,則將導致編譯器錯誤,除非使用@NoArgsConstructor(force = true),否則所有final字段都將初始化為0 / false / null。對於具有約束的字段(例如@NonNull字段),不會生成任何檢查。
@RequiredArgsConstructor為每個需要特殊處理的字段生成一個帶有1個參數的構造函數。所有未初始化的final字段都會獲取一個參數,以及所有未聲明其位置的未標記為@NonNull的字段。
@AllArgsConstructor為類中的每個字段生成一個帶有1個參數的構造函數。標有@NonNull的字段將對這些參數進行空檢查。
With Lombok:
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.NonNull;

@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class ConstructorExample {
private int x, y;
@NonNull
private T description;

@NoArgsConstructor
public static class NoArgsExample {
@NonNull
private String field;
}
}
Native Java:
public class ConstructorExample {
private int x, y;
@NonNull
private T description;

private ConstructorExample(T description) {
if (description == null) throw new NullPointerException("description");
this.description = description;
}

public static ConstructorExample of(T description) {
return new ConstructorExample (description);
}

@java.beans.ConstructorProperties({"x", "y", "description"})
protected ConstructorExample(int x, int y, T description) {
if (description == null) throw new NullPointerException("description");
this.x = x;
this.y = y;
this.description = description;
}

public static class NoArgsExample {
@NonNull
private String field;

public NoArgsExample() {
}

}
}
五、@Data
@Data是一個方便的快捷方式批注,它將@ToString,@EqualsAndHashCode,@ Getter / @Setter和@RequiredArgsConstructor的功能捆綁在一起:換句話說,@Data生成通常與簡單POJO關聯的所有樣板(普通的舊Java對象)和bean:所有字段的getter,所有非final字段的setter,以及涉及類字段的適當的toString,equals和hashCode實現,以及初始化所有final字段以及所有非final字段的構造函數沒有使用@NonNull標記的初始化程序,以確保該字段永遠不會為null。
With Lombok:
import lombok.AccessLevel;
import lombok.Setter;
import lombok.Data;
import lombok.ToString;

@Data
public class DataExample {
private final String name;
@Setter(AccessLevel.PACKAGE)
private int age;
private double score;
private String[] tags;

@ToString(includeFieldNames=true)
@Data(staticConstructor="of")
public static class Exercise {
private final String name;
private final T value;
}
}
Native Java:
import java.util.Arrays;

public class DataExample {
private final String name;
private int age;
private double score;
private String[] tags;

public DataExample(String name) {
this.name = name;
}

public String getName() {
return this.name;
}

void setAge(int age) {
this.age = age;
}

public int getAge() {
return this.age;
}

public void setScore(double score) {
this.score = score;
}

public double getScore() {
return this.score;
}

public String[] getTags() {
return this.tags;
}

public void setTags(String[] tags) {
this.tags = tags;
}

@Override
public String toString() {
return "DataExample(" + this.getName() + ", " + this.getAge() + ", " + this.getScore() + ", " + Arrays.deepToString(this.getTags()) + ")";
}

protected boolean canEqual(Object other) {
return other instanceof DataExample;
}

@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof DataExample)) return false;
DataExample other = (DataExample) o;
if (!other.canEqual((Object)this)) return false;
if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
if (this.getAge() != other.getAge()) return false;
if (Double.compare(this.getScore(), other.getScore()) != 0) return false;
if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;
return true;
}

@Override
public int hashCode() {
final int PRIME = 59;
int result = 1;
final long temp1 = Double.doubleToLongBits(this.getScore());
result = (resultPRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
result = (result
PRIME) + this.getAge();
result = (resultPRIME) + (int)(temp1 ^ (temp1 >>> 32));
result = (result
PRIME) + Arrays.deepHashCode(this.getTags());
return result;
}

public static class Exercise {
private final String name;
private final T value;

private Exercise(String name, T value) {
  this.name = name;
  this.value = value;
}

public static <T> Exercise<T> of(String name, T value) {
  return new Exercise<T>(name, value);
}

public String getName() {
  return this.name;
}

public T getValue() {
  return this.value;
}

@Override 
public String toString() {
  return "Exercise(name=" + this.getName() + ", value=" + this.getValue() + ")";
}

protected boolean canEqual(Object other) {
  return other instanceof Exercise;
}

@Override 
public boolean equals(Object o) {
  if (o == this) return true;
  if (!(o instanceof Exercise)) return false;
  Exercise<?> other = (Exercise<?>) o;
  if (!other.canEqual((Object)this)) return false;
  if (this.getName() == null ? other.getValue() != null : !this.getName().equals(other.getName())) return false;
  if (this.getValue() == null ? other.getValue() != null : !this.getValue().equals(other.getValue())) return false;
  return true;
}

@Override 
public int hashCode() {
  final int PRIME = 59;
  int result = 1;
  result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
  result = (result*PRIME) + (this.getValue() == null ? 43 : this.getValue().hashCode());
  return result;
}

}
}
六、@Value
@Value注解和@Data類似,區別在於它會把所有成員變量默認定義為private final修飾,並且不會生成set方法。
七、@Builder
構建者模式
只能標注到類上,將生成類的一個當前流程的一種鏈式構造工廠,如下:
User buildUser = User.builder().username("riemann").password("123").build();
可配合@Singular注解使用,@Singular注解使用在jdk內部集合類型的屬性,Map類型的屬性以及Guava的com.google.common.collect 的屬性上。例如 未標注@Singular的屬性,一般setter時,會直接覆蓋原來的引用,標注了@Singular的屬性,集合屬性支持添加操作,會在屬性原來的基礎上增加。
With Lombok:
import lombok.Builder;
import lombok.Singular;
import java.util.Set;

@Builder
public class BuilderExample {
@Builder.Default
private long created = System.currentTimeMillis();
private String name;
private int age;
@Singular
private Set occupations;
}
Native Java:
import java.util.Set;

public class BuilderExample {
private long created;
private String name;
private int age;
private Set occupations;

BuilderExample(String name, int age, Set occupations) {
this.name = name;
this.age = age;
this.occupations = occupations;
}

private static long $default$created() {
return System.currentTimeMillis();
}

public static BuilderExampleBuilder builder() {
return new BuilderExampleBuilder();
}

public static class BuilderExampleBuilder {
private long created;
private boolean created$set;
private String name;
private int age;
private java.util.ArrayList occupations;

BuilderExampleBuilder() {
}

public BuilderExampleBuilder created(long created) {
  this.created = created;
  this.created$set = true;
  return this;
}

public BuilderExampleBuilder name(String name) {
  this.name = name;
  return this;
}

public BuilderExampleBuilder age(int age) {
  this.age = age;
  return this;
}

public BuilderExampleBuilder occupation(String occupation) {
  if (this.occupations == null) {
    this.occupations = new java.util.ArrayList<String>();
  }
  
  this.occupations.add(occupation);
  return this;
}

public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {
  if (this.occupations == null) {
    this.occupations = new java.util.ArrayList<String>();
  }

  this.occupations.addAll(occupations);
  return this;
}

public BuilderExampleBuilder clearOccupations() {
  if (this.occupations != null) {
    this.occupations.clear();
  }
  
  return this;
}

public BuilderExample build() {
  // complicated switch statement to produce a compact properly sized immutable set omitted.
  Set<String> occupations = ...;
  return new BuilderExample(created$set ? created : BuilderExample.$default$created(), name, age, occupations);
}

@java.lang.Override
public String toString() {
  return "BuilderExample.BuilderExampleBuilder(created = " + this.created + ", name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
}

}
}
八、@Accessors
鏈式風格
@Accessors批注用於配置lombok如何生成和查找getter和setter。
默認情況下,lombok遵循針對getter和setter的bean規范:例如,名為Pepper的字段的getter是getPepper。但是,有些人可能希望打破bean規范,以得到更好看的API。 @Accessors允許您執行此操作。
可標注在類或屬性上,當然最實用的功能還是標注到類上。
標注到類上,chain屬性設置為true時,類的所有屬性的setter方法返回值將為this,用來支持setter方法的鏈式寫法。如:
new User().setUsername("riemann").setPassword("123");
fluent屬性設置為true時,類的所有getter,setter方法將省略get和set前綴,獲取屬性值直接使用屬性名相同的無參方法,設置屬性值使用屬性名相同的有參方法,並且返回值為this。如:
User user = new User().username("riemann").password("123");
String username = user.username();
String password = user.password();
標注到屬性上,使用prefix設置需要省略的屬性生成getter,setter方法時的前綴,且屬性必須為駝峰式命名。
@Accessors(prefix = "r")
@Getter
@Setter
private String rUsername = "riemann";
編譯之后為
public String getUsername() {
return rUsername;
}
public void setUsername(String rUsername) {
this.rUsername = rUsername;
}
九、@Slf4j and @Log4j
在需要打印日志的類中使用,項目中使用slf4j、log4j日志框架
十、@NonNull
該注解快速判斷是否為空,為空拋出java.lang.NullPointerException。
十一、@Synchronized
注解自動添加到同步機制,生成的代碼並不是直接鎖方法,而是鎖代碼塊, 作用范圍是方法上。
十二、@Cleanup
注解用於確保已分配的資源被釋放(IO的連接關閉)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM