• 使用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是如何帮我们解决这种重复性劳动呢?

    package com.lhy.boot.lombok;
     
    import lombok.Getter;
    import lombok.Setter;
     
    @Getter
    @Setter
    public class GetterSetterExample1 {
     
        private int age = 10;
        
        private String name ="张三丰";
        
        private boolean registerd;
        
        private String sex;
     
    }

    编译后的class:

    package com.lhy.boot.lombok;
     
    public class GetterSetterExample1
    {
      private int age = 10;
     
      private String name = "张三丰";
      private boolean registerd;
      private String sex;
     
      public int getAge()
      {
        return this.age;
      }
     
      public String getName() {
        return this.name;
      }
     
      public boolean isRegisterd() {
        return this.registerd;
      }
     
      public String getSex() {
        return this.sex;
      }
     
      public GetterSetterExample1 setAge(int age) {
        this.age = age;
        return this;
      }
     
      public GetterSetterExample1 setName(String name) {
        this.name = name;
        return this;
      }
     
      public GetterSetterExample1 setRegisterd(boolean registerd) {
        this.registerd = registerd;
        return this;
      }
     
      public GetterSetterExample1 setSex(String sex) {
        this.sex = sex;
        return this;
      }
    }


    通过gettter,setter注解lombok已经帮我们自动生成了getter,setter方法!
    是不是很神奇呢?lombok是怎么的做到的?这个后边再讲,先把lombok ide插件环境搭起来

    下载并引用
    maven项目添加依赖
    <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.16</version>
            </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类型

     import java.util.ArrayList;
    import java.util.HashMap;
    import lombok.val;
     
    public class ValExample {
      public String example() {
        val example = new ArrayList<String>();
        example.add("Hello, World!");
        val foo = example.get(0);
        return foo.toLowerCase();
      }
      
      public void example2() {
        val map = new HashMap<Integer, String>();
        map.put(0, "zero");
        map.put(5, "five");
        for (val entry : map.entrySet()) {
          System.out.printf("%d: %s ", entry.getKey(), entry.getValue());
        }
      }
    }
    翻译后

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Map;
     
    public class ValExample {
      public String example() {
        final ArrayList<String> example = new ArrayList<String>();
        example.add("Hello, World!");
        final String foo = example.get(0);
        return foo.toLowerCase();
      }
      
      public void example2() {
        final HashMap<Integer, String> map = new HashMap<Integer, String>();
        map.put(0, "zero");
        map.put(5, "five");
        for (final Map.Entry<Integer, String> entry : map.entrySet()) {
          System.out.printf("%d: %s ", entry.getKey(), entry.getValue());
        }
      }
    }

    2.@NonNull
    在方法或构造函数的参数上使用@NonNull,lombok将生成一个空值检查语句。
     import lombok.NonNull;
     
    public class NonNullExample extends Something {
      private String name;
      
      public NonNullExample(@NonNull Person person) {
        super("Hello");
        this.name = person.getName();
      }
    }
    翻译后
    import lombok.NonNull;
     
    public class NonNullExample extends Something {
      private String name;
      
      public NonNullExample(@NonNull Person person) {
        super("Hello");
        if (person == null) {
          throw new NullPointerException("person");
        }
        this.name = person.getName();
      }
    }


    3.@Cleanup
    使用该注解能够自动释放io资源
     import lombok.Cleanup;
    import java.io.*;
     
    public class CleanupExample {
      public static void main(String[] args) throws IOException {
        @Cleanup InputStream in = new FileInputStream(args[0]);
        @Cleanup OutputStream out = new FileOutputStream(args[1]);
        byte[] b = new byte[10000];
        while (true) {
          int r = in.read(b);
          if (r == -1) break;
          out.write(b, 0, r);
        }
      }
    }
    翻译后
    import java.io.*;
     
    public class CleanupExample {
      public static void main(String[] args) throws IOException {
        InputStream in = new FileInputStream(args[0]);
        try {
          OutputStream out = new FileOutputStream(args[1]);
          try {
            byte[] b = new byte[10000];
            while (true) {
              int r = in.read(b);
              if (r == -1) break;
              out.write(b, 0, r);
            }
          } finally {
            if (out != null) {
              out.close();
            }
          }
        } finally {
          if (in != null) {
            in.close();
          }
        }
      }
    }
    当然从1.7开始jdk已经提供了try with resources的方式自动回收资源
    static String readFirstLineFromFile(String path) throws IOException {
        try (BufferedReader br = new BufferedReader(new FileReader(path))) {
            return br.readLine();
        }
    }
    4.@Getter/@Setter
    import lombok.AccessLevel;
    import lombok.Getter;
    import lombok.Setter;
     
    public class GetterSetterExample {
      /**
       * Age of the person. Water is wet.
       * 
       * @param age New value for this person's age. Sky is blue.
       * @return The current value of this person's age. Circles are round.
       */
      @Getter @Setter private int age = 10;
      
      /**
       * Name of the person.
       * -- SETTER --
       * Changes the name of this person.
       * 
       * @param name The new value.
       */
      @Setter(AccessLevel.PROTECTED) private String name;
      
      @Override public String toString() {
        return String.format("%s (age: %d)", name, age);
      }
    }
    翻译后
     public class GetterSetterExample {
      /**
       * Age of the person. Water is wet.
       */
      private int age = 10;
     
      /**
       * Name of the person.
       */
      private String name;
      
      @Override public String toString() {
        return String.format("%s (age: %d)", name, age);
      }
      
      /**
       * Age of the person. Water is wet.
       *
       * @return The current value of this person's age. Circles are round.
       */
      public int getAge() {
        return age;
      }
      
      /**
       * Age of the person. Water is wet.
       *
       * @param age New value for this person's age. Sky is blue.
       */
      public void setAge(int age) {
        this.age = age;
      }
      
      /**
       * Changes the name of this person.
       *
       * @param name The new value.
       */
      protected void setName(String name) {
        this.name = name;
      }
    }
    扩展配置:
    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)
    import lombok.ToString;
     
    @ToString(exclude="id")
    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.getName();
      }
      
      @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;
        }
      }
    }
    翻译后
     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.getName();
      }
      
      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) + ")";
      }
    }
    扩展配置:
    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方法

     import lombok.EqualsAndHashCode;
     
    @EqualsAndHashCode(exclude={"id", "shape"})
    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;
      }
      
      @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;
        }
      }
    }
    翻译后
     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 = (result*PRIME) + (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;
        }
      }
    }
    扩展配置:

    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
    给类增加无参构造器 指定参数的构造器 包含所有参数的构造器

     import lombok.AccessLevel;
    import lombok.RequiredArgsConstructor;
    import lombok.AllArgsConstructor;
    import lombok.NonNull;
     
    @RequiredArgsConstructor(staticName = "of")
    @AllArgsConstructor(access = AccessLevel.PROTECTED)
    public class ConstructorExample<T> {
      private int x, y;
      @NonNull private T description;
      
      @NoArgsConstructor
      public static class NoArgsExample {
        @NonNull private String field;
      }
    }
    翻译后
     public class ConstructorExample<T> {
      private int x, y;
      @NonNull private T description;
      
      private ConstructorExample(T description) {
        if (description == null) throw new NullPointerException("description");
        this.description = description;
      }
      
      public static <T> ConstructorExample<T> of(T description) {
        return new ConstructorExample<T>(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() {
        }
      }
    }
    扩展配置:
    lombok.anyConstructor.suppressConstructorProperties = [true | false] (default: false)如果将其设置为true,那么lombok将跳过添加一个@java.bean.ConstructorProperties生成的构造器。这在android和GWT开发中很有用,因为这些注释通常不可用。

    8.@Data

    包含以下注解的集合

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

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

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


    9.@Value

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

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

    10.@Builder

    建筑者模式

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

     import lombok.Builder;
    import lombok.Singular;
    import java.util.Set;
     
    @Builder
    public class BuilderExample {
      private String name;
      private int age;
      @Singular private Set<String> occupations;
    }
    翻译后
     import java.util.Set;
     
    public class BuilderExample {
      private String name;
      private int age;
      private Set<String> occupations;
      
      BuilderExample(String name, int age, Set<String> occupations) {
        this.name = name;
        this.age = age;
        this.occupations = occupations;
      }
      
      public static BuilderExampleBuilder builder() {
        return new BuilderExampleBuilder();
      }
      
      public static class BuilderExampleBuilder {
        private String name;
        private int age;
        private java.util.ArrayList<String> occupations;
        
        BuilderExampleBuilder() {
        }
        
        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.
          // go to https://projectlombok.org/features/Singular-snippet.html to see it.
          Set<String> occupations = ...;
          return new BuilderExample(name, age, occupations);
        }
        
        @java.lang.Override
        public String toString() {
          return "BuilderExample.BuilderExampleBuilder(name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
        }
      }
    }

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

     import lombok.SneakyThrows;
     
    public class SneakyThrowsExample implements Runnable {
      @SneakyThrows(UnsupportedEncodingException.class)
      public String utf8ToString(byte[] bytes) {
        return new String(bytes, "UTF-8");
      }
      
      @SneakyThrows
      public void run() {
        throw new Throwable();
      }
    }
    翻译后:
     import lombok.Lombok;
     
    public class SneakyThrowsExample implements Runnable {
      public String utf8ToString(byte[] bytes) {
        try {
          return new String(bytes, "UTF-8");
        } catch (UnsupportedEncodingException e) {
          throw Lombok.sneakyThrow(e);
        }
      }
      
      public void run() {
        try {
          throw new Throwable();
        } catch (Throwable t) {
          throw Lombok.sneakyThrow(t);
        }
      }
    }


    12.@Synchronized

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

     import lombok.Synchronized;
     
    public class SynchronizedExample {
      private final Object readLock = new Object();
      
      @Synchronized
      public static void hello() {
        System.out.println("world");
      }
      
      @Synchronized
      public int answerToLife() {
        return 42;
      }
      
      @Synchronized("readLock")
      public void foo() {
        System.out.println("bar");
      }
    }
    翻译后
    public class SynchronizedExample {
      private static final Object $LOCK = new Object[0];
      private final Object $lock = new Object[0];
      private final Object readLock = new Object();
      
      public static void hello() {
        synchronized($LOCK) {
          System.out.println("world");
        }
      }
      
      public int answerToLife() {
        synchronized($lock) {
          return 42;
        }
      }
      
      public void foo() {
        synchronized(readLock) {
          System.out.println("bar");
        }
      }
    }

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

    13.@Getter(lazy=true)

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

    import lombok.Getter;
     
    public class GetterLazyExample {
      @Getter(lazy=true) private final double[] cached = expensive();
      
      private double[] expensive() {
        double[] result = new double[1000000];
        for (int i = 0; i < result.length; i++) {
          result[i] = Math.asin(i);
        }
        return result;
      }
    }
    翻译后
     public class GetterLazyExample {
      private final java.util.concurrent.AtomicReference<java.lang.Object> cached = new java.util.concurrent.AtomicReference<java.lang.Object>();
      
      public double[] getCached() {
        java.lang.Object value = this.cached.get();
        if (value == null) {
          synchronized(this.cached) {
            value = this.cached.get();
            if (value == null) {
              final double[] actualValue = expensive();
              value = actualValue == null ? this.cached : actualValue;
              this.cached.set(value);
            }
          }
        }
        return (double[])(value == this.cached ? null : value);
      }
      
      private double[] expensive() {
        double[] result = new double[1000000];
        for (int i = 0; i < result.length; i++) {
          result[i] = Math.asin(i);
        }
        return result;
      }
    }

    14.@Log

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

     import lombok.extern.java.Log;
    import lombok.extern.slf4j.Slf4j;
     
    @Log
    public class LogExample {
      
      public static void main(String... args) {
        log.error("Something's wrong here");
      }
    }
     
    @Slf4j
    public class LogExampleOther {
      
      public static void main(String... args) {
        log.error("Something else is wrong here");
      }
    }
     
    @CommonsLog(topic="CounterLog")
    public class LogExampleCategory {
     
      public static void main(String... args) {
        log.error("Calling the 'CounterLog' with a message");
      }
    }
    翻译为
     public class LogExample {
      private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
      
      public static void main(String... args) {
        log.error("Something's wrong here");
      }
    }
     
    public class LogExampleOther {
      private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class);
      
      public static void main(String... args) {
        log.error("Something else is wrong here");
      }
    }
     
    public class LogExampleCategory {
      private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("CounterLog");
     
      public static void main(String... args) {
        log.error("Calling the 'CounterLog' with a message");
      }
    }

    所有支持的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://projectlombok.org/features/all
    --------------------- 
    作者:再见尼罗河 
    来源:CSDN 
    原文:https://blog.csdn.net/v2sking/article/details/73431364 
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    VECTOR的用法
    【转】C/C++中的Split函数(字符串自动分割)
    【转】动态树
    【实验】vector性质
    【转】Android操作系统安全研究系列——键盘记录
    D8神贴
    【操作系统】修改WIN7下的文件关联与默认程序
    【转】探寻C++最快的读取文件的方案(方法未论证)
    如何在60分钟之内过掉600个单词
    【转】动态树:实现
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13317439.html
Copyright © 2020-2023  润新知