java工具jar包—Lombok


如何引入

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

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

 

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM