java工具jar包—Lombok

如何引入

maven工程,直接引入lombok的jar依赖即可:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.18</version>
</dependency>

 

@Accessors(chain=true)

链式访问,该注解设置chain=true,生成setter方法返回this(也就是返回的是对象),代替了默认的返回void。

package com.pollyduan;

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain=true)
public class User {
    private Integer id;
    private String name;
    private Integer age;

    public static void main(String[] args) {
        //开起chain=true后可以使用链式的set
        User user=new User().setAge(31).setName("pollyduan");//返回对象
        System.out.println(user);
    }

}

 

 

@Accessors(fluent = true)

与chain=true类似,区别在于getter和setter不带set和get前缀。

package com.pollyduan;

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(fluent=true)
public class User {
    private Integer id;
    private String name;
    private Integer age;

    public static void main(String[] args) {
        //fluent=true开启后默认chain=true,故这里也可以使用链式set
        User user=new User().age(31).name("pollyduan");//不需要写set
        System.out.println(user);
    }

}

 

val

我们定义一个常量都会这样写:

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\n", entry.getKey(), entry.getValue());  
    }  
  }  
}  

 

  但是, 自从有了Lombok, 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\n", entry.getKey(), entry.getValue());  
    }  
  }  
}  

 

@NotNull

对比下面两端代码:

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(Person person) {  
    super("Hello");  
    if (person == null) {  
      throw new NullPointerException("person");  
    }  
    this.name = person.getName();  
  }  
}

 

估计看过guava代码的应该都看到过这种annotation。其实NotNull包括了两种Exception,有一个可选的annotation参数,通过exceptionType,可以决定当前位置是用IllegalArgumentException还是NPE,当然默认值就是NPE了。在Lombok中有一个好处就是如果使用了如@Data这样的Lombok annotation,也会默认触发@NotNull 的, 同时如果把@NotNull加到了原始类型上,你将收获一个warning。

@Cleanup

使用前:

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

 

使用后: 

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

 

单单从代码的行数上面就可以知道已经精简了不少,同时,代码的可读性也进一步提高。从代码中我们可以容易的看出,@Cleanup的作用就是在当前变量不在有效范围内的时候,对其进行自动的资源回收。在Java中的Stream上使用Cleanup Annotation,就是对其调用close方法。

 但是,请大家注意,Cleanup 存在一个小问题:

官网给出了提示,如果你的代码中出现了异常,那么会触发cleanup方法抛出异常,导致把原始异常吞掉,这样就导致你在上层不知道发生了什么事情,这个事情很严重啊,但是如果说你是在调用close方法的时候出了异常,那么Cleanup这个annotation是不会把异常吞掉的。 同时,官网也指出,作者也没有找到更好的方式去解决这个问题,如果他们找到了会立刻fix这个问题,否则也就只能等待Java 有可能在Update的时候出现新的解决方案。

@Getter, @Setter

想必你一定为写这样的代码而苦恼:

public class GetterSetterExample {  

  private int age = 10;  
  
  private String name;  
    
  @Override public String toString() {  
    return String.format("%s (age: %d)", name, age);  
  }  
    
  public int getAge() {  
    return age;  
  }  
    
  public void setAge(int age) {  
    this.age = age;  
  }  
    
  protected void setName(String name) {  
    this.name = name;  
  }  
} 

 

 那么这两个annotation到底能干什么呢?

import lombok.AccessLevel;  
import lombok.Getter;  
import lombok.Setter;  
  
public class GetterSetterExample {  

  @Getter @Setter private int age = 10;  
    
  @Setter(AccessLevel.PROTECTED) private String name;  
    
  @Override public String toString() {  
    return String.format("%s (age: %d)", name, age);  
  }  
}  

 

 如果没有设置AccessLevel属性,则生成的默认方法为public的。如果想要使get,set方法不生效,则可以使用一个特殊的AccessLevel 选项 “NONE”。

同样给大家一点小的建议:

在使用的时候如果当前bean中包括某个方法,恰好要和生成的方法名字一样,则Lombok不会再处理生成,无论是不是两个函数的方法是重载。例如:如果类中包含String get(String anme), 则不会再为bean生成一个新的方法。

@ToString

我们的代码经常这样: 

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) + ")";  
  }  
}  

 其实,我们的代码可以这样:

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

 

 这样的方便方式节省了好多拼接字符串的功夫。

 lombok.toString.includeFieldNames = [true | false] (default: true)是否包含field的信息,如果值为true ,则可以在toString方法中给出field 的name。

lombok.toString.doNotUseGetters = [true | false] (default: false)如果值为true,则Lombok会直接获取field 而不是通过get方法获取值。

@EqualsAndHashCode

实现equals, hashCode方法是在编程生活中再常见不过的一个东西了,那么自然@EqualsAndHashCode 这个annotation就成为了一个非常方便的工具。默认情况下,被这个annotation标注的class会用到除了 static,transient修饰的所有属性作为判断标准,当然和之前的annotation一样,可是使用exclude选项除掉不想要的属性。也可以通过callSuper包含父类的equals 和 hashCode。 当然如果你的class 没有继承任何其他的class,你却写了callSuper,那么会收获一个编译报错。

你只要这样用:

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 ? 0 : 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的优势所在。几个需要注意的点是,对于Array类型的变量,如果需要进行equals和hashCode的时候需要调用工具类的Arrays中的deepHashCode, deepEquals完成比较。

Constructor

在Lombok中,生成构造方法的annotation一共有三个,@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsContructor。使用这三个annotation来完成项目中对于不同构造方法的需求。

 @NoArgsConstructor : 生成一个无参数的构造方法,这个annotation在与其他的annotation配合起来使用的时候更加能凸显出他的重要性,例如在使用hibernate这种框架的时候,如果有一个有参数的构造方法的时候,NoArgsConstructor会展示出他的作用。

 @RequiredArgsConstructor: 会生成一个包含常量,和标识了NotNull的变量 的构造方法。生成的构造方法是private,如何想要对外提供使用可以使用staticName选项生成一个static方法。

 @AllArgsContructor:  会生成一个包含所有变量,同时如果变量使用了NotNull annotation , 会进行是否为空的校验。

我们来看一下官方给出的一个例子:

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

 

上面的例子用Java代码翻译一下就是:

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() {  
    }  
  }  
}  

 

 如果是@AllArgsConstructor 在生成的构造函数上会生成一@ConstructorProperties 的Java annotation, 当然也可以通过将suppressConstructorProperties 设置为true来禁用@ConstructorProperties 。 如果你知道@ConstructorProperties 是干什么用的,那么一定就知道@NoArgsConstructor为什么没有这个配置参数了。 

提示一点:@ConstructorProperties 只能用在JDK 6 中。

@Data,@Value

作为之前介绍几个annotation的一个统称,可谓整理了方便,@Data直接修饰POJO or beans, getter所有的变量,setter所有不为final的变量。如果你不需要默认的生成方式,直接填写你需要的annotation的就可以了。默认生成的所有的annotation都是public的,如果需要不同权限修饰符可以使用AccessLevel.NONE选项。当然@Data 也可以使用staticConstructor选项生成一个静态方法。
使用Data annotation可以简便的完成自己想要的内容:
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 ? 0 : 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 ? 0 : this.getName().hashCode());  
      result = (result*PRIME) + (this.getValue() == null ? 0 : this.getValue().hashCode());  
      return result;  
    }  
  }  
}

 与@Data相对应的@Value, 两个annotation的主要区别就是如果变量不加@NonFinal ,@Value会给所有的弄成final的。当然如果是final的话,就没有set方法了。 

import lombok.AccessLevel;  
import lombok.experimental.NonFinal;  
import lombok.experimental.Value;  
import lombok.experimental.Wither;  
import lombok.ToString;  
  
@Value public class ValueExample {  
  String name;  
  @Wither(AccessLevel.PACKAGE) @NonFinal int age;  
  double score;  
  protected String[] tags;  
    
  @ToString(includeFieldNames=true)  
  @Value(staticConstructor="of")  
  public static class Exercise<T> {  
    String name;  
    T value;  
  }  
}  

 使用后:

import java.util.Arrays;  
  
public final class ValueExample {  
  private final String name;  
  private int age;  
  private final double score;  
  protected final String[] tags;  
    
  @java.beans.ConstructorProperties({"name", "age", "score", "tags"})  
  public ValueExample(String name, int age, double score, String[] tags) {  
    this.name = name;  
    this.age = age;  
    this.score = score;  
    this.tags = tags;  
  }  
    
  public String getName() {  
    return this.name;  
  }  
    
  public int getAge() {  
    return this.age;  
  }  
    
  public double getScore() {  
    return this.score;  
  }  
    
  public String[] getTags() {  
    return this.tags;  
  }  
    
  @java.lang.Override  
  public boolean equals(Object o) {  
    if (o == this) return true;  
    if (!(o instanceof ValueExample)) return false;  
    final ValueExample other = (ValueExample)o;  
    final Object this$name = this.getName();  
    final Object other$name = other.getName();  
    if (this$name == null ? other$name != null : !this$name.equals(other$name)) 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;  
  }  
    
  @java.lang.Override  
  public int hashCode() {  
    final int PRIME = 59;  
    int result = 1;  
    final Object $name = this.getName();  
    result = result * PRIME + ($name == null ? 0 : $name.hashCode());  
    result = result * PRIME + this.getAge();  
    final long $score = Double.doubleToLongBits(this.getScore());  
    result = result * PRIME + (int)($score >>> 32 ^ $score);  
    result = result * PRIME + Arrays.deepHashCode(this.getTags());  
    return result;  
  }  
    
  @java.lang.Override  
  public String toString() {  
    return "ValueExample(name=" + getName() + ", age=" + getAge() + ", score=" + getScore() + ", tags=" + Arrays.deepToString(getTags()) + ")";  
  }  
    
  ValueExample withAge(int age) {  
    return this.age == age ? this : new ValueExample(name, age, score, tags);  
  }  
    
  public static final 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;  
    }  
      
    @java.lang.Override  
    public boolean equals(Object o) {  
      if (o == this) return true;  
      if (!(o instanceof ValueExample.Exercise)) return false;  
      final Exercise<?> other = (Exercise<?>)o;  
      final Object this$name = this.getName();  
      final Object other$name = other.getName();  
      if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;  
      final Object this$value = this.getValue();  
      final Object other$value = other.getValue();  
      if (this$value == null ? other$value != null : !this$value.equals(other$value)) return false;  
      return true;  
    }  
      
    @java.lang.Override  
    public int hashCode() {  
      final int PRIME = 59;  
      int result = 1;  
      final Object $name = this.getName();  
      result = result * PRIME + ($name == null ? 0 : $name.hashCode());  
      final Object $value = this.getValue();  
      result = result * PRIME + ($value == null ? 0 : $value.hashCode());  
      return result;  
    }  
      
    @java.lang.Override  
    public String toString() {  
      return "ValueExample.Exercise(name=" + getName() + ", value=" + getValue() + ")";  
    }  
  }  
}

@Sychronized

@Sychronized 是一个处理线程安全问题的annotation, 他的使用方法和关键字 synchronized比较类似,但是有一些不同点就是,关键字synchronized是锁定当前对象(this指针) , 而@Synchronized则会锁定一个private的常量。如果当前类中没有这个常量,就会自动生成一个。

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

 如果当前锁定的方法是一个静态的方法的话,会自动生成一个静态常量,如果是一个普通方法的话会生成一个普通常量,类型为Object 

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

@Getter(lazy=true)

最后终于到了一个高级点的annotation的用法了,使用lazy版的getter annotation, 会提高代码效率,同时由Lombok帮助你管理线程安全问题,大可放心。先看一段代码: 

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

 


使用了getter这个annotation可以在实际使用到cached的时候生成cached,同时,Lombok会自动去管理线程安全的问题,不会存在重复赋值的问题。

Log

Lombok封装了许多主流的Log库,提供了一系列关于Log 的annotation。下面就是所有的annotation会代表哪些特定的类 :

@CommonsLog  
Creates private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);  
@Log  
Creates private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());  
@Log4j  
Creates private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);  
@Log4j2  
Creates private 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  
Creates private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

 

就用其中的几个举个例子吧:

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

 


@SneakyThrows

@SneakyThrows的用法比较简单,其实就是对于异常的一个整理,将checked exception 看做unchecked exception, 不处理,直接扔掉。 减少了到处写catch的不便利性。比如在线程中,catch所有异常,再比如在一些不太可能发生异常的地方,但是你又必须cache checked exception的地方使用这个annotation会显得代码比较规整,易读。或许也会显得高大上一点吧

 

import lombok.SneakyThrows;

public class SneakyThrowsExample implements Runnable {
   @SneakyThrows(UnsupportedEncodingException.class)
   public String utf8ToString(byte[] bytes) {
     return new String(bytes, &quot;UTF-8&quot;);
   }
   
   @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, &quot;UTF-8&quot;);
     } catch (UnsupportedEncodingException e) {
       throw Lombok.sneakyThrow(e);
     }
   }
   
   public void run() {
     try {
       throw new Throwable();
     } catch (Throwable t) {
       throw Lombok.sneakyThrow(t);
     }
   }
}

 

参考资料

http://himichaelchu.iteye.com/category/324280

 

posted on 2017-12-19 13:02  Louis军  阅读(12147)  评论(0编辑  收藏  举报

导航