使用lombok提高编码效率

Lombok简介



Project Lombok makes java a spicier language by adding ‘handlers’ that know >how to build and compile simple, boilerplate-free, not-quite-java code.


github上官方是这么描述lombok的:
         lombok项目通过增加处理程序使我们的java语言更加刺激(简洁和快速)。


先看个简单示例:

 
我们做java开发的时候,最不少写的就是javabean了,bean字段都需要添加gettter/setter方法,往往我们只能一次又一次的使用ide生成gettter,setter 构造器等等。

lombok是如何帮我们解决这种重复性劳动呢?


 
 
  1. package com.lhy.boot.lombok;
  2. import lombok.Getter;
  3. import lombok.Setter;
  4. @Getter
  5. @Setter
  6. public class GetterSetterExample1 {
  7. private int age = 10;
  8. private String name = "张三丰";
  9. private boolean registerd;
  10. private String sex;
  11. }

编译后的class:


 
 
  1. package com.lhy.boot.lombok;
  2. public class GetterSetterExample1
  3. {
  4. private int age = 10;
  5. private String name = "张三丰";
  6. private boolean registerd;
  7. private String sex;
  8. public int getAge()
  9. {
  10. return this.age;
  11. }
  12. public String getName() {
  13. return this.name;
  14. }
  15. public boolean isRegisterd() {
  16. return this.registerd;
  17. }
  18. public String getSex() {
  19. return this.sex;
  20. }
  21. public GetterSetterExample1 setAge(int age) {
  22. this.age = age;
  23. return this;
  24. }
  25. public GetterSetterExample1 setName(String name) {
  26. this.name = name;
  27. return this;
  28. }
  29. public GetterSetterExample1 setRegisterd(boolean registerd) {
  30. this.registerd = registerd;
  31. return this;
  32. }
  33. public GetterSetterExample1 setSex(String sex) {
  34. this.sex = sex;
  35. return this;
  36. }
  37. }


通过gettter,setter注解lombok已经帮我们自动生成了getter,setter方法!

是不是很神奇呢?lombok是怎么的做到的?这个后边再讲,先把lombok ide插件环境搭起来

下载并引用

maven项目添加依赖


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

或者到官网下载jar包  https://projectlombok.org/download

安装ide插件

myeclipse/eclipse

下载完成后 命令行运行 

java -jar lombok-1.16.16.jar
 
 
弹出安装界面:



specify location 选择myeclipse安装目录,eclipse同理。

点击 install/update 安装完成。


或者将jar包放入myeclipse 根目录下

myeclipse.ini文件末尾添加:

-javaagent:lombok-1.16.16.jar
 
 
重启myeclipse即可。

安装完毕后

打开myeclipse about 可以看到


证明插件安装完成


IntelliJ IDEA

  • 定位到 File > Settings > Plugins
  • 点击 Browse repositories…
  • 搜索 Lombok Plugin
  • 点击 Install plugin
  • 重启 IDEA

Lombok注解详解

全局配置文件

我们可以从项目根目录下新建一个lombok.config(当然目录不是固定的,lombok会搜索所有lombok.config文件)
在这个文件加入一行
config.stopBubbling = true 
表示该文件目录为根目录,lombok将从该目录下开始搜索。
每个子目录都可以配置lombok.config 作用范围只在该目录下,并且覆盖父目录的配置。


Lombok通常为所有生成的节点生成注释,添加@javax.annotation.Generated 。

可以用:

lombok.addJavaxGeneratedAnnotation = false 设置取消



下面看下lombok提供了哪些有趣的注解。


1.@val @var

使用Lombok ,java也能够像javascript一样使用弱类型定义变量了

val注解变量申明是final类型 var注解变量是非final类型


 
 
  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. public void example2() {
  12. val map = new HashMap<Integer, String>();
  13. map.put( 0, "zero");
  14. map.put( 5, "five");
  15. for (val entry : map.entrySet()) {
  16. System.out.printf( "%d: %s\n", entry.getKey(), entry.getValue());
  17. }
  18. }
  19. }
翻译后


 
 
  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. public void example2() {
  12. final HashMap<Integer, String> map = new HashMap<Integer, String>();
  13. map.put( 0, "zero");
  14. map.put( 5, "five");
  15. for ( final Map.Entry<Integer, String> entry : map.entrySet()) {
  16. System.out.printf( "%d: %s\n", entry.getKey(), entry.getValue());
  17. }
  18. }
  19. }

2.@NonNull

在方法或构造函数的参数上使用@NonNull,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. }
翻译后


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


3.@Cleanup

使用该注解能够自动释放io资源


 
 
  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. }
翻译后


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

当然从1.7开始jdk已经提供了try with resources的方式自动回收资源

  
  
  1. static String readFirstLineFromFile(String path) throws IOException {
  2. try (BufferedReader br = new BufferedReader( new FileReader(path))) {
  3. return br.readLine();
  4. }
  5. }
4.@Getter/@Setter

  
  
  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. }
翻译后

  
  
  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. }
扩展配置:
lombok.accessors.chain = [ true |  false] (default: false)如果设置为true,生成的setter将返回this(而不是void),通过这个配置我们可以像jquery一样愉快的链式编程了。可以在类加增加一个@Accessors 注解 配置chain属性,优先于全局配置。
lombok.accessors.fluent = [ true |  false] (default: false)如果设置为true,生成的getter和setter将不会使用bean标准的get、is或set进行前缀;相反,方法将使用与字段相同的名称(减去前缀)。可以在类加增加一个@Accessors注解,配置fluent属性,优先于全局配置
lombok.accessors.prefix +=  a field prefix (default: empty list) 给getter/setter方法增加前缀 例如配置 +=M 原有的 getFoo方法将变为getMFoo方法。 lombok.getter.noIsPrefix = [ true |  false] (default: false) 如果设置为true,那么boolean型字段生成的getter将使用get前缀而不是默认的is前缀


5.@ToString

生成一个toString方法,log debug神器

默认的toString格式为:ClassName(fieldName= fieleValue ,fieldName1=fieleValue)


 
 
  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.getName();
  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. }
翻译后

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

扩展配置:

lombok.toString.includeFieldNames = [true | false] (default: true)

通常,lombok以fieldName=fieldValue的形式为每个字段生成一个toString响应的片段。如果设置为false,lombok将省略字段的名称,可以在该注解上配置属性includeFieldNames来标示包含的字段,这样可以覆盖默认配置。

lombok.toString.doNotUseGetters  = [ true  |  false ] (default: false)
如果设置为true,lombok将直接访问字段,而不是在生成tostring方法时使用getter(如果可用)。可以在该注解上配置属性doNotUseGetters来标示不使用getter的字段,这样可以覆盖默认配置。


6.@EqualsAndHashCode

给类增加equals和hashCode方法


 
 
  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. }
翻译后

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

扩展配置:

lombok.config增加:

lombok.equalsAndHashCode.doNotUseGetters = [true | false]
(default: false)如果设置为true,lombok将直接访问字段,而不是在生成equals和hashcode方法时使用getter(如果可用)。
可以在该注解上配置属性donotusegetter来标示不使用getter的字段,这样可以覆盖默认配置。

lombok.equalsAndHashCode.callSuper = [call | skip | warn]
(default: warn)如果设置为call,lombok将生成对hashCode的超类实现的调用。如果设置为skip,则不会生成这样的调用。默认行为warn类似于skip,并带有附加警告。



7.@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor

给类增加无参构造器 指定参数的构造器 包含所有参数的构造器


 
 
  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. }
翻译后


 
 
  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. }
扩展配置:

lombok.anyConstructor.suppressConstructorProperties = [true | false]
(default: false)如果将其设置为true,那么lombok将跳过添加一个@java.bean.ConstructorProperties生成的构造器。这在android和GWT开发中很有用,因为这些注释通常不可用。


8.@Data

包含以下注解的集合

@ToString,@EqualsAndHashCode,所有字段的 @Getter 所有非final字段的@Setter ,@RequiredArgsConstructor


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

翻译后

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


9.@Value

@value是@data的不可变对象 (不可变对象的用处和创建:https://my.oschina.net/jasonultimate/blog/166810

所有字段都是私有的,默认情况下是final的,并且不会生成setter。默认情况下,类本身也是final的,因为不可变性不能强制转化为子类。与@data一样,有用toString()、equals()和hashCode()方法也是生成的,每个字段都有一个getter方法,并且一个覆盖每个参数的构造器也会生成。


10.@Builder

建筑者模式

是现在比较推崇的一种构建值对象的方式。


 
 
  1. import lombok.Builder;
  2. import lombok.Singular;
  3. import java.util.Set;
  4. @Builder
  5. public class BuilderExample {
  6. private String name;
  7. private int age;
  8. @Singular private Set<String> occupations;
  9. }
翻译后

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

11.@SneakyThrows

把checked异常转化为unchecked异常,好处是不用再往上层方法抛出了,美其名曰暗埋异常


 
 
  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. }
翻译后:

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


12.@Synchronized

类似于Synchronized 关键字 但是可以隐藏同步锁


 
 
  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. }
翻译后

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

xianzjdk推荐使用Lock了,这个仅供参考


13.@Getter(lazy=true)

如果getter方法计算值需要大量CPU,或者值占用大量内存,第一次调用这个getter,它将一次计算一个值,然后从那时开始缓存它


 
 
  1. import lombok.Getter;
  2. public class GetterLazyExample {
  3. @Getter(lazy= true) private final double[] cached = expensive();
  4. private double[] expensive() {
  5. double[] result = new double[ 1000000];
  6. for ( int i = 0; i < result.length; i++) {
  7. result[i] = Math.asin(i);
  8. }
  9. return result;
  10. }
  11. }
翻译后

 
 
  1. public class GetterLazyExample {
  2. private final java.util.concurrent.AtomicReference<java.lang.Object> cached = new java.util.concurrent.AtomicReference<java.lang.Object>();
  3. public double[] getCached() {
  4. java.lang.Object value = this.cached.get();
  5. if (value == null) {
  6. synchronized( this.cached) {
  7. value = this.cached.get();
  8. if (value == null) {
  9. final double[] actualValue = expensive();
  10. value = actualValue == null ? this.cached : actualValue;
  11. this.cached.set(value);
  12. }
  13. }
  14. }
  15. return ( double[])(value == this.cached ? null : value);
  16. }
  17. private double[] expensive() {
  18. double[] result = new double[ 1000000];
  19. for ( int i = 0; i < result.length; i++) {
  20. result[i] = Math.asin(i);
  21. }
  22. return result;
  23. }
  24. }


14.@Log

可以生成各种log对象,方便多了


 
 
  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. }
翻译为

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

所有支持的log类型:

@CommonsLog
Createsprivate static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@JBossLog
Createsprivate static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
@Log
Createsprivate static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j
Createsprivate static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
@Log4j2
Createsprivate static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4j
Creates private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4j
Createsprivate static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

扩展配置:

lombok.log.fieldName = an identifier (default: log).生成log字段的名称 默认为log
lombok.log.fieldIsStatic = [true | false]
(default: true)生成log是否是static的 默认为static




官方文档说明:https://projectlombok.org/features/all

Lombok原理

lombok通过简单的注解标志就能够实现复杂的代码生成,他是怎么做到的?

lombok注解不是我们常见的runtime注解,而是source注解或者class注解,
在没有jsr之前我们可以通过反射在运行是获取注解值,但是这样效率很低,而且没办法做到编译检查,对开发人员一些不合的编码错误给出警告,


JSR 269: Pluggable Annotation Processing API ( https://www.jcp.org/en/jsr/detail?id=269) 出现后,我们可以在javac的编译器利用注解来完成对class文件的修改。

lombok本质上就是这样的一个实现了"JSR 269 API"的程序。在使用javac的过程中,它产生作用的具体流程如下:
1)javac对源代码进行分析,生成一棵抽象语法树(AST)
2)运行过程中调用实现了"JSR 269 API"的lombok程序
3)此时lombok就对第一步骤得到的AST进行处理,找到@Data注解所在类对应的语法树(AST),然后修改该语法树(AST),增加getter和setter方法定义的相应树节点
4)javac使用修改后的抽象语法树(AST)生成字节码文件,即给class增加新的节点(代码块)

ide中使用Lombok的注意事项


1.项目中要使用lombok 不仅ide要支持(否则一堆错误),项目中也要引入jar包

2.如果配置lombok.config文件,修改文件的属性值后,并不会自动重新编译class文件,ide编辑器也不会自动更新,所有每次修改配置文件后最后关闭java文件窗口重新打开,并且clean下项目

文章转载

https://blog.csdn.net/v2sking/article/details/73431364
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值