Java Lombok

一、@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:

  1. import lombok.AccessLevel;
  2. import lombok.Getter;
  3. import lombok.Setter;
  4. public class GetterSetterExample {
  5. @Getter
  6. @Setter
  7. private int age = 10;
  8. @Setter(AccessLevel.PROTECTED)
  9. private String name;
  10. @Override
  11. public String toString() {
  12. return String.format("%s (age: %d)", name, age);
  13. }
  14. }

Native Java:

  1. public class GetterSetterExample {
  2. private int age = 10;
  3. private String name;
  4. @Override
  5. public String toString() {
  6. return String.format("%s (age: %d)", name, age);
  7. }
  8. public int getAge() {
  9. return age;
  10. }
  11. public void setAge(int age) {
  12. this.age = age;
  13. }
  14. protected void setName(String name) {
  15. this.name = name;
  16. }
  17. }

二、@ToString

任何类定义都可以使用@ToString注释,以使lombok生成toString()方法的实现。
默认情况下,将打印所有非静态字段。如果要跳过某些字段,可以使用@ ToString.Exclude注释这些字段。或者,可以通过使用@ToString(onlyExplicitlyIncluded = true),然后使用@ToString.Include标记要包含的每个字段,来确切指定希望使用的字段。
通过将callSuper设置为true,可以将toString的超类实现的输出包含到输出中。请注意,java.lang.Object中toString() 的默认实现几乎毫无意义。
With Lombok:

  1. import lombok.ToString;
  2. @ToString
  3. public class ToStringExample {
  4. private static final int STATIC_VAR = 10;
  5. private String name;
  6. private Shape shape = new Square(5, 10);
  7. private String[] tags;
  8. @ToString.Exclude
  9. private int id;
  10. public String getName() {
  11. return this.name;
  12. }
  13. @ToString(callSuper=true, includeFieldNames=true)
  14. public static class Square extends Shape {
  15. private final int width, height;
  16. public Square(int width, int height) {
  17. this.width = width;
  18. this.height = height;
  19. }
  20. }
  21. }

Native Java:

  1. import java.util.Arrays;
  2. public class ToStringExample {
  3. private static final int STATIC_VAR = 10;
  4. private String name;
  5. private Shape shape = new Square(5, 10);
  6. private String[] tags;
  7. private int id;
  8. public String getName() {
  9. return this.name;
  10. }
  11. public static class Square extends Shape {
  12. private final int width, height;
  13. public Square(int width, int height) {
  14. this.width = width;
  15. this.height = height;
  16. }
  17. @Override
  18. public String toString() {
  19. return "Square(super=" + super.toString() + ", width=" + this.width + ", height=" + this.height + ")";
  20. }
  21. }
  22. @Override
  23. public String toString() {
  24. return "ToStringExample(" + this.getName() + ", " + this.shape + ", " + Arrays.deepToString(this.tags) + ")";
  25. }
  26. }

三、@EqualsAndHashCode

任何类定义都可以使用@EqualsAndHashCode进行注释,以使lombok生成equals(Object other)hashCode()方法的实现。默认情况下,它将使用所有非静态,非瞬态字段,但是您可以通过使用@EqualsAndHashCode.Include标记类型成员来修改使用哪些字段(甚至指定要使用各种方法的输出)。 @EqualsAndHashCode.Exclude。或者,可以通过使用@ EqualsAndHashCode.Include标记并使用@EqualsAndHashCode(onlyExplicitlyIncluded = true)来精确指定要使用的字段或方法。
如果将@EqualsAndHashCode应用于扩展另一个类的类,则此功能会有些棘手。通常,为此类自动生成equalshashCode方法是一个坏主意,因为超类还定义了字段,该字段也需要equals / hashCode代码,但不会生成此代码。通过将callSuper设置为true,可以在生成的方法中包括超类的equalshashCode方法。
With Lombok:

  1. import lombok.EqualsAndHashCode;
  2. @EqualsAndHashCode
  3. public class EqualsAndHashCodeExample {
  4. private transient int transientVar = 10;
  5. private String name;
  6. private double score;
  7. @EqualsAndHashCode.Exclude
  8. private Shape shape = new Square(5, 10);
  9. private String[] tags;
  10. @EqualsAndHashCode.Exclude
  11. private int id;
  12. public String getName() {
  13. return this.name;
  14. }
  15. @EqualsAndHashCode(callSuper=true)
  16. public static class Square extends Shape {
  17. private final int width, height;
  18. public Square(int width, int height) {
  19. this.width = width;
  20. this.height = height;
  21. }
  22. }
  23. }

Native Java:

  1. import java.util.Arrays;
  2. public class EqualsAndHashCodeExample {
  3. private transient int transientVar = 10;
  4. private String name;
  5. private double score;
  6. private Shape shape = new Square(5, 10);
  7. private String[] tags;
  8. private int id;
  9. public String getName() {
  10. return this.name;
  11. }
  12. @Override
  13. public boolean equals(Object o) {
  14. if (o == this) return true;
  15. if (!(o instanceof EqualsAndHashCodeExample)) return false;
  16. EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o;
  17. if (!other.canEqual((Object)this)) return false;
  18. if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
  19. if (Double.compare(this.score, other.score) != 0) return false;
  20. if (!Arrays.deepEquals(this.tags, other.tags)) return false;
  21. return true;
  22. }
  23. @Override
  24. public int hashCode() {
  25. final int PRIME = 59;
  26. int result = 1;
  27. final long temp1 = Double.doubleToLongBits(this.score);
  28. result = (result*PRIME) + (this.name == null ? 43 : this.name.hashCode());
  29. result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
  30. result = (result*PRIME) + Arrays.deepHashCode(this.tags);
  31. return result;
  32. }
  33. protected boolean canEqual(Object other) {
  34. return other instanceof EqualsAndHashCodeExample;
  35. }
  36. public static class Square extends Shape {
  37. private final int width, height;
  38. public Square(int width, int height) {
  39. this.width = width;
  40. this.height = height;
  41. }
  42. @Override
  43. public boolean equals(Object o) {
  44. if (o == this) return true;
  45. if (!(o instanceof Square)) return false;
  46. Square other = (Square) o;
  47. if (!other.canEqual((Object)this)) return false;
  48. if (!super.equals(o)) return false;
  49. if (this.width != other.width) return false;
  50. if (this.height != other.height) return false;
  51. return true;
  52. }
  53. @Override
  54. public int hashCode() {
  55. final int PRIME = 59;
  56. int result = 1;
  57. result = (result*PRIME) + super.hashCode();
  58. result = (result*PRIME) + this.width;
  59. result = (result*PRIME) + this.height;
  60. return result;
  61. }
  62. protected boolean canEqual(Object other) {
  63. return other instanceof Square;
  64. }
  65. }
  66. }

四、@AllArgsConstructor@RequiredArgsConstructor@NoArgsConstructor

@NoArgsConstructor将生成没有参数的构造函数。如果字段由final修饰,则将导致编译器错误,除非使用@NoArgsConstructor(force = true),否则所有final字段都将初始化为0 / false / null。对于具有约束的字段(例如@NonNull字段),不会生成任何检查。
@RequiredArgsConstructor为每个需要特殊处理的字段生成一个带有1个参数的构造函数。所有未初始化的final字段都会获取一个参数,以及所有未声明其位置的未标记为@NonNull的字段。
@AllArgsConstructor为类中的每个字段生成一个带有1个参数的构造函数。标有@NonNull的字段将对这些参数进行空检查。
With Lombok:

  1. import lombok.AccessLevel;
  2. import lombok.RequiredArgsConstructor;
  3. import lombok.AllArgsConstructor;
  4. import lombok.NonNull;
  5. @RequiredArgsConstructor(staticName = "of")
  6. @AllArgsConstructor(access = AccessLevel.PROTECTED)
  7. public class ConstructorExample<T> {
  8. private int x, y;
  9. @NonNull
  10. private T description;
  11. @NoArgsConstructor
  12. public static class NoArgsExample {
  13. @NonNull
  14. private String field;
  15. }
  16. }

Native Java:

  1. public class ConstructorExample<T> {
  2. private int x, y;
  3. @NonNull
  4. private T description;
  5. private ConstructorExample(T description) {
  6. if (description == null) throw new NullPointerException("description");
  7. this.description = description;
  8. }
  9. public static <T> ConstructorExample<T> of(T description) {
  10. return new ConstructorExample<T>(description);
  11. }
  12. @java.beans.ConstructorProperties({"x", "y", "description"})
  13. protected ConstructorExample(int x, int y, T description) {
  14. if (description == null) throw new NullPointerException("description");
  15. this.x = x;
  16. this.y = y;
  17. this.description = description;
  18. }
  19. public static class NoArgsExample {
  20. @NonNull
  21. private String field;
  22. public NoArgsExample() {
  23. }
  24. }
  25. }

五、@Data

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

  1. import lombok.AccessLevel;
  2. import lombok.Setter;
  3. import lombok.Data;
  4. import lombok.ToString;
  5. @Data
  6. public class DataExample {
  7. private final String name;
  8. @Setter(AccessLevel.PACKAGE)
  9. private int age;
  10. private double score;
  11. private String[] tags;
  12. @ToString(includeFieldNames=true)
  13. @Data(staticConstructor="of")
  14. public static class Exercise<T> {
  15. private final String name;
  16. private final T value;
  17. }
  18. }

Native Java:

  1. import java.util.Arrays;
  2. public class DataExample {
  3. private final String name;
  4. private int age;
  5. private double score;
  6. private String[] tags;
  7. public DataExample(String name) {
  8. this.name = name;
  9. }
  10. public String getName() {
  11. return this.name;
  12. }
  13. void setAge(int age) {
  14. this.age = age;
  15. }
  16. public int getAge() {
  17. return this.age;
  18. }
  19. public void setScore(double score) {
  20. this.score = score;
  21. }
  22. public double getScore() {
  23. return this.score;
  24. }
  25. public String[] getTags() {
  26. return this.tags;
  27. }
  28. public void setTags(String[] tags) {
  29. this.tags = tags;
  30. }
  31. @Override
  32. public String toString() {
  33. return "DataExample(" + this.getName() + ", " + this.getAge() + ", " + this.getScore() + ", " + Arrays.deepToString(this.getTags()) + ")";
  34. }
  35. protected boolean canEqual(Object other) {
  36. return other instanceof DataExample;
  37. }
  38. @Override
  39. public boolean equals(Object o) {
  40. if (o == this) return true;
  41. if (!(o instanceof DataExample)) return false;
  42. DataExample other = (DataExample) o;
  43. if (!other.canEqual((Object)this)) return false;
  44. if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
  45. if (this.getAge() != other.getAge()) return false;
  46. if (Double.compare(this.getScore(), other.getScore()) != 0) return false;
  47. if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;
  48. return true;
  49. }
  50. @Override
  51. public int hashCode() {
  52. final int PRIME = 59;
  53. int result = 1;
  54. final long temp1 = Double.doubleToLongBits(this.getScore());
  55. result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
  56. result = (result*PRIME) + this.getAge();
  57. result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
  58. result = (result*PRIME) + Arrays.deepHashCode(this.getTags());
  59. return result;
  60. }
  61. public static class Exercise<T> {
  62. private final String name;
  63. private final T value;
  64. private Exercise(String name, T value) {
  65. this.name = name;
  66. this.value = value;
  67. }
  68. public static <T> Exercise<T> of(String name, T value) {
  69. return new Exercise<T>(name, value);
  70. }
  71. public String getName() {
  72. return this.name;
  73. }
  74. public T getValue() {
  75. return this.value;
  76. }
  77. @Override
  78. public String toString() {
  79. return "Exercise(name=" + this.getName() + ", value=" + this.getValue() + ")";
  80. }
  81. protected boolean canEqual(Object other) {
  82. return other instanceof Exercise;
  83. }
  84. @Override
  85. public boolean equals(Object o) {
  86. if (o == this) return true;
  87. if (!(o instanceof Exercise)) return false;
  88. Exercise<?> other = (Exercise<?>) o;
  89. if (!other.canEqual((Object)this)) return false;
  90. if (this.getName() == null ? other.getValue() != null : !this.getName().equals(other.getName())) return false;
  91. if (this.getValue() == null ? other.getValue() != null : !this.getValue().equals(other.getValue())) return false;
  92. return true;
  93. }
  94. @Override
  95. public int hashCode() {
  96. final int PRIME = 59;
  97. int result = 1;
  98. result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
  99. result = (result*PRIME) + (this.getValue() == null ? 43 : this.getValue().hashCode());
  100. return result;
  101. }
  102. }
  103. }

六、@Value

@Value注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。

七、@Builder

构建者模式
只能标注到类上,将生成类的一个当前流程的一种链式构造工厂,如下:

  1. User buildUser = User.builder().username("riemann").password("123").build();

可配合@Singular注解使用,@Singular注解使用在jdk内部集合类型的属性,Map类型的属性以及Guavacom.google.common.collect 的属性上。例如 未标注@Singular的属性,一般setter时,会直接覆盖原来的引用,标注了@Singular的属性,集合属性支持添加操作,会在属性原来的基础上增加。
With Lombok:

  1. import lombok.Builder;
  2. import lombok.Singular;
  3. import java.util.Set;
  4. @Builder
  5. public class BuilderExample {
  6. @Builder.Default
  7. private long created = System.currentTimeMillis();
  8. private String name;
  9. private int age;
  10. @Singular
  11. private Set<String> occupations;
  12. }

Native Java:

  1. import java.util.Set;
  2. public class BuilderExample {
  3. private long created;
  4. private String name;
  5. private int age;
  6. private Set<String> occupations;
  7. BuilderExample(String name, int age, Set<String> occupations) {
  8. this.name = name;
  9. this.age = age;
  10. this.occupations = occupations;
  11. }
  12. private static long $default$created() {
  13. return System.currentTimeMillis();
  14. }
  15. public static BuilderExampleBuilder builder() {
  16. return new BuilderExampleBuilder();
  17. }
  18. public static class BuilderExampleBuilder {
  19. private long created;
  20. private boolean created$set;
  21. private String name;
  22. private int age;
  23. private java.util.ArrayList<String> occupations;
  24. BuilderExampleBuilder() {
  25. }
  26. public BuilderExampleBuilder created(long created) {
  27. this.created = created;
  28. this.created$set = true;
  29. return this;
  30. }
  31. public BuilderExampleBuilder name(String name) {
  32. this.name = name;
  33. return this;
  34. }
  35. public BuilderExampleBuilder age(int age) {
  36. this.age = age;
  37. return this;
  38. }
  39. public BuilderExampleBuilder occupation(String occupation) {
  40. if (this.occupations == null) {
  41. this.occupations = new java.util.ArrayList<String>();
  42. }
  43. this.occupations.add(occupation);
  44. return this;
  45. }
  46. public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {
  47. if (this.occupations == null) {
  48. this.occupations = new java.util.ArrayList<String>();
  49. }
  50. this.occupations.addAll(occupations);
  51. return this;
  52. }
  53. public BuilderExampleBuilder clearOccupations() {
  54. if (this.occupations != null) {
  55. this.occupations.clear();
  56. }
  57. return this;
  58. }
  59. public BuilderExample build() {
  60. // complicated switch statement to produce a compact properly sized immutable set omitted.
  61. Set<String> occupations = ...;
  62. return new BuilderExample(created$set ? created : BuilderExample.$default$created(), name, age, occupations);
  63. }
  64. @java.lang.Override
  65. public String toString() {
  66. return "BuilderExample.BuilderExampleBuilder(created = " + this.created + ", name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
  67. }
  68. }
  69. }

八、@Accessors

链式风格
@Accessors批注用于配置lombok如何生成和查找gettersetter
默认情况下,lombok遵循针对gettersetterbean规范:例如,名为Pepper的字段的gettergetPepper。但是,有些人可能希望打破bean规范,以得到更好看的API@Accessors允许您执行此操作。
可标注在类或属性上,当然最实用的功能还是标注到类上。
标注到类上,chain属性设置为true时,类的所有属性的setter方法返回值将为this,用来支持setter方法的链式写法。如:

  1. new User().setUsername("riemann").setPassword("123");

fluent属性设置为true时,类的所有gettersetter方法将省略getset前缀,获取属性值直接使用属性名相同的无参方法,设置属性值使用属性名相同的有参方法,并且返回值为this。如:

  1. User user = new User().username("riemann").password("123");
  2. String username = user.username();
  3. String password = user.password();

标注到属性上,使用prefix设置需要省略的属性生成gettersetter方法时的前缀,且属性必须为驼峰式命名。

  1. @Accessors(prefix = "r")
  2. @Getter
  3. @Setter
  4. private String rUsername = "riemann";

编译之后为

  1. public String getUsername() {
  2. return rUsername;
  3. }
  4. public void setUsername(String rUsername) {
  5. this.rUsername = rUsername;
  6. }

九、@Slf4j and @Log4j

在需要打印日志的类中使用,项目中使用slf4jlog4j日志框架

十、@NonNull

该注解快速判断是否为空,为空抛出java.lang.NullPointerException

十一、@Synchronized

注解自动添加到同步机制,生成的代码并不是直接锁方法,而是锁代码块, 作用范围是方法上。

十二、@Cleanup

注解用于确保已分配的资源被释放(IO的连接关闭)。