Skip to content
YellowStar5 edited this page Aug 10, 2019 · 2 revisions

@Data

所有的都合到一起:@ToString@ EqualsAndHashCode,所有字段的 @Getter,所有非 final 字段的 @Setter@RequiredArgsConstructor 的快捷方式!

@Data 是一个方便的快捷方式注解,它将 @ToString@ EqualsAndHashCode@Getter / @Setter@RequiredArgsConstructor 的特性捆绑在一起:换句话说,@Data 生成通常与简单POJO相关的所有样板(普通旧Java对象) )和bean:所有字段的 getter ,所有非 final 字段的 setter ,以及涉及类字段的相应 toStringequalshashCode 实现,以及初始化所有final字段的构造函数,以及所有非 final 字段没有使用 @NonNull 标记的初始化程序,以确保该字段永远不为空。

@Data 就像在类上隐含 @Getter@Setter@ ToTtring@EqualsAndHashCode@RequiredArgsConstructor 注解一样(除非已经存在任何显式编写的构造函数,否则会生成构造函数)。但是,无法使用 @Data 设置这些注解的参数(例如 callSuperincludeFieldNamesexclude)。如果你需要为这些参数中的任何一个设置非默认值,只需显式添加这些注解; @Data 非常聪明,可以遵循这些注释。

所有生成的 getter 和 setter 都将是 public 的。要覆盖访问级别,请使用显式的 @Setter 和/或 @Getter 注解对字段或类进行注释。你还可以使用此注解(通过将其与 AccessLevel.NONE 组合)来完全禁止生成 getter 和/或 setter。

标记为 transient 的所有字段都不会被 hashCodeequals 考虑。将完全跳过所有静态字段(不考虑任何生成的方法,并且不会为它们创建 setter / getter)。

如果类已经包含与通常生成的方法具有相同名称和参数个数的方法,则不会生成该方法,也不会发出警告或错误。例如,如果你已经有一个签名为 equals(AnyType param) 的方法,则不会生成 equals 方法,即使从技术上讲,由于具有不同的参数类型,它可能是完全不同的方法。同样的规则适用于构造函数(任何显式构造函数都会阻止 @Data 生成一个),以及toStringequals 和所有 getter 和 setter 。你可以使用 @lombok.experimental.Tolerate 标记任何构造函数或方法,以将它们隐藏在lombok中。

@Data 可以很好地处理字段的泛型参数。为了在为具有泛型的类构造对象时减少样板代码,可以使用 staticConstructor 参数来生成私有构造函数,以及返回新实例的静态方法。这样,javac将推断变量名称。因此,通过这样声明: @Data(staticConstructor="of") class Foo<T> { private T x;} 你可以通过写 Foo.of(5) 来创建Foo的新实例 ;而不必写: new Foo<Integer>(5);.

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<T> {
   private final String name;
   private final T value;
 }
}

Vanilla 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 = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
    result = (result*PRIME) + this.getAge();
    result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
    result = (result*PRIME) + Arrays.deepHashCode(this.getTags());
    return result;
  }
  
  public static class Exercise<T> {
    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;
    }
  }
}

支持的配置键

lombok.data.flagUsage = [ warning | error (默认: 未设置) 如果已配置,Lombok会将@Data的任何用法标记为警告或错误。

Small print

请参阅 @ToString@EqualsAndHashCode@ Getter/@Setter@RequiredArgsConstructor 的Small print。

各种众所周知的关于空值的注释会导致插入空值检查,并将其复制到参数中。有关详细信息,请参阅 Getter/ Setter 文档的small print.。

默认情况下,任何以 $ 符号开头的变量都会自动排除。 你可以通过指定显式注释(例如 @Getter@ToString )并使用 of 参数来包含它们。