当前位置:   article > 正文

lombok使用总结

import lombok.val依赖

前提

这篇文章主要介绍lombok的使用,至于lombok的源码和原理暂不探究,可以看上一篇文章插件化注解处理API去了解lombok的基本原理。参考资料:

简介

Project Lombok是一个java库,它可以自动插入到编辑器中,并构建工具,使java更加丰富。再也不用getter或equals方法了。尽早访问未来的java特性,比如val等等。这个就是lombok的官方简介(例如Jdk9中新增的val关键字在lombok中很早就出现了)。lombok实际上是基于JSR-269的插件化注解处理API,在编译期间对使用了特定注解的类、方法、属性或者代码片段进行动态修改,添加或者实现其自定义功能的类库。

安装

maven依赖

在项目中使用到lombok的注解必须引入其依赖:

  1. <dependency>
  2. <groupId>org.projectlombok</groupId>
  3. <artifactId>lombok</artifactId>
  4. <version>${version}</version>
  5. </dependency>

当前的最新版本为:1.16.20。

插件

如果不为IDE安装lombok的插件,IDE无法识别lombok编译期动态生成的代码,表现为代码块标红,因此需要安装其插件,插件地址:https://projectlombok.org/download。

下载完成后,将会得到一个jar包lombok-xx.xx.xx.jar,直接使用命令java -jar lombok-xx.xx.xx.jar运行即可,然后按照指引安装到IDEA、eclipse或者myeclipse。

lombok注解

@val

@val用于声明修饰符为final的局部变量类型,使用的时候不需要编写实际的类型,这一点依赖于编译器的类型推导。@val的作用域是局部变量。举例如下:

使用lombok:

  1. import java.util.ArrayList;
  2. import java.util.HashMap;
  3. import lombok.val;
  4. public class ValExample {
  5. public String example() {
  6. val example = new ArrayList<String>();
  7. example.add("Hello, World!");
  8. val foo = example.get(0);
  9. return foo.toLowerCase();
  10. }
  11. }

相当于原生Java:

  1. import java.util.ArrayList;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. public class ValExample {
  5. public String example() {
  6. final ArrayList<String> example = new ArrayList<String>();
  7. example.add("Hello, World!");
  8. final String foo = example.get(0);
  9. return foo.toLowerCase();
  10. }
  11. }

@var

@var的功能类似于@val,不过@var修饰的是非final修饰的局部变量。

@NonNull

@NonNull的作用域是属性(field)、方法参数或、构造函数参数以及局部变量(LOCAL_VARIABLE),为这些参数添加一个空检查语句,基本格式是:if(param == null) {throw new NullPointerException("param ");}

使用lombok:

  1. import lombok.NonNull;
  2. public class NonNullExample extends Something {
  3. private String name;
  4. public NonNullExample(@NonNull Person person) {
  5. super("Hello");
  6. this.name = person.getName();
  7. }
  8. }

相当于原生Java:

  1. import lombok.NonNull;
  2. public class NonNullExample extends Something {
  3. private String name;
  4. public NonNullExample(@NonNull Person person) {
  5. super("Hello");
  6. if (person == null) {
  7. throw new NullPointerException("person");
  8. }
  9. this.name = person.getName();
  10. }
  11. }

@Cleanup

你可以使用@Cleanup来确保在代码执行路径退出当前范围之前自动清理给定的资源,一般使用在流的局部变量的关闭。可以通过value()指定关闭资源的方法名,注意,关闭资源的方法必须是无参void方法,默认的关闭资源方法名称是"close"。

使用lombok:

  1. import lombok.Cleanup;
  2. import java.io.*;
  3. public class CleanupExample {
  4. public static void main(String[] args) throws IOException {
  5. @Cleanup InputStream in = new FileInputStream(args[0]);
  6. @Cleanup OutputStream out = new FileOutputStream(args[1]);
  7. byte[] b = new byte[10000];
  8. while (true) {
  9. int r = in.read(b);
  10. if (r == -1) break;
  11. out.write(b, 0, r);
  12. }
  13. }
  14. }

相当于原生Java:

  1. import java.io.*;
  2. public class CleanupExample {
  3. public static void main(String[] args) throws IOException {
  4. InputStream in = new FileInputStream(args[0]);
  5. try {
  6. OutputStream out = new FileOutputStream(args[1]);
  7. try {
  8. byte[] b = new byte[10000];
  9. while (true) {
  10. int r = in.read(b);
  11. if (r == -1) break;
  12. out.write(b, 0, r);
  13. }
  14. } finally {
  15. if (out != null) {
  16. out.close();
  17. }
  18. }
  19. } finally {
  20. if (in != null) {
  21. in.close();
  22. }
  23. }
  24. }
  25. }

@Getter/@Setter

@Getter/@Setter作用域是属性或者类。@Getter为指定属性或者类中的所有属性生成Getter方法,@Setter指定非final属性或者类中的所有非final属性生成Setter方法。可以通过@Getter/@Setter的value()中的AccessLevel属性来指定生成的方法的修饰符,可以通过@Getter的布尔值属性lazy来指定是否延迟加载。

使用lombok:

  1. import lombok.AccessLevel;
  2. import lombok.Getter;
  3. import lombok.Setter;
  4. public class GetterSetterExample {
  5. /**
  6. * Age of the person. Water is wet.
  7. *
  8. * @param age New value for this person's age. Sky is blue.
  9. * @return The current value of this person's age. Circles are round.
  10. */
  11. @Getter @Setter private int age = 10;
  12. /**
  13. * Name of the person.
  14. * -- SETTER --
  15. * Changes the name of this person.
  16. *
  17. * @param name The new value.
  18. */
  19. @Setter(AccessLevel.PROTECTED) private String name;
  20. @Override public String toString() {
  21. return String.format("%s (age: %d)", name, age);
  22. }
  23. }

相当于原生Java:

  1. public class GetterSetterExample {
  2. /**
  3. * Age of the person. Water is wet.
  4. */
  5. private int age = 10;
  6. /**
  7. * Name of the person.
  8. */
  9. private String name;
  10. @Override public String toString() {
  11. return String.format("%s (age: %d)", name, age);
  12. }
  13. /**
  14. * Age of the person. Water is wet.
  15. *
  16. * @return The current value of this person's age. Circles are round.
  17. */
  18. public int getAge() {
  19. return age;
  20. }
  21. /**
  22. * Age of the person. Water is wet.
  23. *
  24. * @param age New value for this person's age. Sky is blue.
  25. */
  26. public void setAge(int age) {
  27. this.age = age;
  28. }
  29. /**
  30. * Changes the name of this person.
  31. *
  32. * @param name The new value.
  33. */
  34. protected void setName(String name) {
  35. this.name = name;
  36. }
  37. }

@ToString

@ToString的作用域是类,主要作用是覆盖类中的toString方法。@ToString的属性比较多,简介如下:

  • includeFieldNames():布尔值,默认为true,true表示拼接toString的时候使用属性名。
  • exclude():字符串数组,默认为空,用于通过属性名排除拼接toString时使用的属性。
  • of():exclude()属性的对立属性,意思就是include。
  • callSuper():布尔值,默认为false,是否调用父类的属性。
  • doNotUseGetters():布尔值,默认为false,true表示拼接toString的时候使用属性值而不是其Getter方法。

下面是官方例子:

使用lombok:

  1. import lombok.ToString;
  2. @ToString(exclude="id")
  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. private int id;
  9. public String getName() {
  10. return this.name;
  11. }
  12. @ToString(callSuper=true, includeFieldNames=true)
  13. public static class Square extends Shape {
  14. private final int width, height;
  15. public Square(int width, int height) {
  16. this.width = width;
  17. this.height = height;
  18. }
  19. }
  20. }

相当于原生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.getName();
  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 public String toString() {
  18. return "Square(super=" + super.toString() + ", width=" + this.width + ", height=" + this.height + ")";
  19. }
  20. }
  21. @Override public String toString() {
  22. return "ToStringExample(" + this.getName() + ", " + this.shape + ", " + Arrays.deepToString(this.tags) + ")";
  23. }
  24. }

@EqualsAndHashCode

@EqualsAndHashCode的作用域是类,用于生成equals()和hashCode()方法。此注解的属性比较多,不过和@ToString类似。举例如下:

使用lombok:

  1. import lombok.EqualsAndHashCode;
  2. @EqualsAndHashCode(exclude={"id", "shape"})
  3. public class EqualsAndHashCodeExample {
  4. private transient int transientVar = 10;
  5. private String name;
  6. private double score;
  7. private Shape shape = new Square(5, 10);
  8. private String[] tags;
  9. private int id;
  10. public String getName() {
  11. return this.name;
  12. }
  13. @EqualsAndHashCode(callSuper=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. }

相当于原生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 public boolean equals(Object o) {
  13. if (o == this) return true;
  14. if (!(o instanceof EqualsAndHashCodeExample)) return false;
  15. EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o;
  16. if (!other.canEqual((Object)this)) return false;
  17. if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
  18. if (Double.compare(this.score, other.score) != 0) return false;
  19. if (!Arrays.deepEquals(this.tags, other.tags)) return false;
  20. return true;
  21. }
  22. @Override public int hashCode() {
  23. final int PRIME = 59;
  24. int result = 1;
  25. final long temp1 = Double.doubleToLongBits(this.score);
  26. result = (result*PRIME) + (this.name == null ? 43 : this.name.hashCode());
  27. result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
  28. result = (result*PRIME) + Arrays.deepHashCode(this.tags);
  29. return result;
  30. }
  31. protected boolean canEqual(Object other) {
  32. return other instanceof EqualsAndHashCodeExample;
  33. }
  34. public static class Square extends Shape {
  35. private final int width, height;
  36. public Square(int width, int height) {
  37. this.width = width;
  38. this.height = height;
  39. }
  40. @Override public boolean equals(Object o) {
  41. if (o == this) return true;
  42. if (!(o instanceof Square)) return false;
  43. Square other = (Square) o;
  44. if (!other.canEqual((Object)this)) return false;
  45. if (!super.equals(o)) return false;
  46. if (this.width != other.width) return false;
  47. if (this.height != other.height) return false;
  48. return true;
  49. }
  50. @Override public int hashCode() {
  51. final int PRIME = 59;
  52. int result = 1;
  53. result = (result*PRIME) + super.hashCode();
  54. result = (result*PRIME) + this.width;
  55. result = (result*PRIME) + this.height;
  56. return result;
  57. }
  58. protected boolean canEqual(Object other) {
  59. return other instanceof Square;
  60. }
  61. }
  62. }

@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor

这三个注解的作用域都是类。@NoArgsConstructor作用是生成一个无参数的构造函数。@AllArgsConstructor作用是生成一个具有所有字段的构造函数。@RequiredArgsConstructor的作用是为每一个使用了final或者@NonNull修饰的属性都生成一个只有一个参数的构造函数。这三个注解都可以通过staticName()指定构造的命名,通过access()指定构造的修饰符。@NoArgsConstructor的属性force()默认值为false,当类中存在final属性的时候使用了@NoArgsConstructor会编译错误,如果force()值为true,那么会把final修饰的属性作为"无参数构造"的参数,并且把属性赋值为0、null或者false。

使用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 private T description;
  10. @NoArgsConstructor
  11. public static class NoArgsExample {
  12. @NonNull private String field;
  13. }
  14. }

相当于原生Java:

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

@Data

@Data的作用域是类,相当于同时应用了@Getter、@Setter、@ToString、@EqualsAndHashCode、@RequiredArgsConstructor。如果已经显示自定义过构造函数,就不会再自动生成构造函数了。举例如下:

使用lombok:

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

相当于原生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 public String toString() {
  32. return "DataExample(" + this.getName() + ", " + this.getAge() + ", " + this.getScore() + ", " + Arrays.deepToString(this.getTags()) + ")";
  33. }
  34. protected boolean canEqual(Object other) {
  35. return other instanceof DataExample;
  36. }
  37. @Override public boolean equals(Object o) {
  38. if (o == this) return true;
  39. if (!(o instanceof DataExample)) return false;
  40. DataExample other = (DataExample) o;
  41. if (!other.canEqual((Object)this)) return false;
  42. if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
  43. if (this.getAge() != other.getAge()) return false;
  44. if (Double.compare(this.getScore(), other.getScore()) != 0) return false;
  45. if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;
  46. return true;
  47. }
  48. @Override public int hashCode() {
  49. final int PRIME = 59;
  50. int result = 1;
  51. final long temp1 = Double.doubleToLongBits(this.getScore());
  52. result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
  53. result = (result*PRIME) + this.getAge();
  54. result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
  55. result = (result*PRIME) + Arrays.deepHashCode(this.getTags());
  56. return result;
  57. }
  58. public static class Exercise<T> {
  59. private final String name;
  60. private final T value;
  61. private Exercise(String name, T value) {
  62. this.name = name;
  63. this.value = value;
  64. }
  65. public static <T> Exercise<T> of(String name, T value) {
  66. return new Exercise<T>(name, value);
  67. }
  68. public String getName() {
  69. return this.name;
  70. }
  71. public T getValue() {
  72. return this.value;
  73. }
  74. @Override public String toString() {
  75. return "Exercise(name=" + this.getName() + ", value=" + this.getValue() + ")";
  76. }
  77. protected boolean canEqual(Object other) {
  78. return other instanceof Exercise;
  79. }
  80. @Override public boolean equals(Object o) {
  81. if (o == this) return true;
  82. if (!(o instanceof Exercise)) return false;
  83. Exercise<?> other = (Exercise<?>) o;
  84. if (!other.canEqual((Object)this)) return false;
  85. if (this.getName() == null ? other.getValue() != null : !this.getName().equals(other.getName())) return false;
  86. if (this.getValue() == null ? other.getValue() != null : !this.getValue().equals(other.getValue())) return false;
  87. return true;
  88. }
  89. @Override public int hashCode() {
  90. final int PRIME = 59;
  91. int result = 1;
  92. result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
  93. result = (result*PRIME) + (this.getValue() == null ? 43 : this.getValue().hashCode());
  94. return result;
  95. }
  96. }
  97. }

@Value

@Value的作用域是类,和@Data类似,但是用于不可变类型。生成的类和所有字段都设置为final,所有字段都为private,自动生成Getter但是没有Setter,会生成初始化所有字段的构造函数。相当于同时应用了final、 @ToString、 @EqualsAndHashCode、 @AllArgsConstructor 、@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)和@Getter。

使用lombok:

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

相当于原生Java:

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

@Builder

@Builder的作用域是类,使用此注解后类中新增一个成员类(Builder)将会使用构建者模式,编译时增加了一个Builder内部类和全字段的构造器。@Builder.Default用于指定Builder中的属性的默认值,@Singular用于告诉lombok当前属性类型是集合类型,lombok会为信任的集合类型添加"adder"方法而不是"setter"方法。

使用lombok:

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

相当于原生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. }

@Synchronized

@Synchronized的作用域是方法,用于方法同步,使用此注解后,方法体中的代码块自动包含在一个synchronize块中。synchronize块加锁的对象一定是类中的一个成员属性,可以通过@Synchronized的value()指定,如果不存在则由lombok新建,一般是private final Object $lock = new Object[0];

使用lombok:

  1. import lombok.Synchronized;
  2. public class SynchronizedExample {
  3. private final Object readLock = new Object();
  4. @Synchronized
  5. public static void hello() {
  6. System.out.println("world");
  7. }
  8. @Synchronized
  9. public int answerToLife() {
  10. return 42;
  11. }
  12. @Synchronized("readLock")
  13. public void foo() {
  14. System.out.println("bar");
  15. }
  16. }

相当于原生Java:

  1. public class SynchronizedExample {
  2. private static final Object $LOCK = new Object[0];
  3. private final Object $lock = new Object[0];
  4. private final Object readLock = new Object();
  5. public static void hello() {
  6. synchronized($LOCK) {
  7. System.out.println("world");
  8. }
  9. }
  10. public int answerToLife() {
  11. synchronized($lock) {
  12. return 42;
  13. }
  14. }
  15. public void foo() {
  16. synchronized(readLock) {
  17. System.out.println("bar");
  18. }
  19. }
  20. }

@SneakyThrows

@SneakyThrows的作用域是构造或者方法,用于自动捕获(隐藏)检查异常。我们知道,java对于检查异常,需要在编码时进行捕获,或者抛出。该注解的作用是将检查异常包装为运行时异常,那么编码时就无需处理异常了。

提示:不过这并不是友好的编码方式,因为你编写的api的使用者,不能显式的获知需要处理检查异常。

使用lombok:

  1. import lombok.SneakyThrows;
  2. public class SneakyThrowsExample implements Runnable {
  3. @SneakyThrows(UnsupportedEncodingException.class)
  4. public String utf8ToString(byte[] bytes) {
  5. return new String(bytes, "UTF-8");
  6. }
  7. @SneakyThrows
  8. public void run() {
  9. throw new Throwable();
  10. }
  11. }

相当于原生Java:

  1. import lombok.Lombok;
  2. public class SneakyThrowsExample implements Runnable {
  3. public String utf8ToString(byte[] bytes) {
  4. try {
  5. return new String(bytes, "UTF-8");
  6. } catch (UnsupportedEncodingException e) {
  7. throw Lombok.sneakyThrow(e);
  8. }
  9. }
  10. public void run() {
  11. try {
  12. throw new Throwable();
  13. } catch (Throwable t) {
  14. throw Lombok.sneakyThrow(t);
  15. }
  16. }
  17. }

@Log

@Log的作用域是类,用于生成日志API句柄。目前支持的类型如下:

  1. @CommonsLog
  2. 相当于在类中定义了:private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
  3. @JBossLog
  4. 相当于在类中定义了:private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
  5. @Log
  6. 相当于在类中定义了:private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
  7. @Log4j
  8. 相当于在类中定义了:private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
  9. @Log4j2
  10. 相当于在类中定义了:private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
  11. @Slf4j
  12. 相当于在类中定义了:private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
  13. @XSlf4j
  14. 相当于在类中定义了:private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

使用lombok:

  1. import lombok.extern.java.Log;
  2. import lombok.extern.slf4j.Slf4j;
  3. @Log
  4. public class LogExample {
  5. public static void main(String... args) {
  6. log.error("Something's wrong here");
  7. }
  8. }
  9. @Slf4j
  10. public class LogExampleOther {
  11. public static void main(String... args) {
  12. log.error("Something else is wrong here");
  13. }
  14. }
  15. @CommonsLog(topic="CounterLog")
  16. public class LogExampleCategory {
  17. public static void main(String... args) {
  18. log.error("Calling the 'CounterLog' with a message");
  19. }
  20. }

相当于原生Java:

  1. public class LogExample {
  2. private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
  3. public static void main(String... args) {
  4. log.error("Something's wrong here");
  5. }
  6. }
  7. public class LogExampleOther {
  8. private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class);
  9. public static void main(String... args) {
  10. log.error("Something else is wrong here");
  11. }
  12. }
  13. public class LogExampleCategory {
  14. private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("CounterLog");
  15. public static void main(String... args) {
  16. log.error("Calling the 'CounterLog' with a message");
  17. }
  18. }

小结

其实从实现的角度来看,lombok并不是一个十分奇特的框架,它用到的技术已经是"很老的"Jdk6的一个特性,但是它表现出来的特性确实令人感觉它就是奇技淫巧。毕竟是奇技淫巧,很多不了解的人就会望然生畏,觉得使用了它很可能会导致系统出现无法预知的BUG之类(这里吐槽一下,笔者所在的公司禁用lombok)。其实,基于插件化注解处理API生成代码是位于编译期间,如果出现任何问题,很明显编译是不可能通过的。如果觉得lombok有问题,大可以去翻看每一个编译后的文件,看它们有没有表现异常。lombok在日常编码中可以极大提高效率,因此它一定是百益而无一害的。

(全文完)

转载于:https://www.cnblogs.com/throwable/p/9139922.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/650736
推荐阅读
相关标签
  

闽ICP备14008679号