Lombok快速上手(安装、使用与注解参数)

Lombok插件安装与使用说明

在实习中发现项目中IDE一直报检查错误,原来是使用了Lombok注解的黑科技,这里整理了一些平常编码中能遇到的全部关于它的使用详解,其实lombok项目的产生就是为了省去咱们手动建立getter和setter方法等等一些基本组件代码的麻烦,它可以在咱们编译源码的时候自动帮咱们生成getter和setter方法。即它最终可以达到的效果是:在源码中没有getter和setter等组件方法,可是在编译生成的字节码文件中有getter和setter等组件方法。git

常见参数

  1. @Setter 注解在类或字段,注解在类时为全部字段生成setter方法,注解在字段上时只为该字段生成setter方法。
  2. @Getter 使用方法同上,区别在于生成的是getter方法。
  3. @ToString 注解在类,添加toString方法。
  4. @EqualsAndHashCode 注解在类,生成hashCode和equals方法。
  5. @NoArgsConstructor 注解在类,生成无参的构造方法。
  6. @RequiredArgsConstructor 注解在类,为类中须要特殊处理的字段生成构造方法,好比final和被@NonNull注解的字段。
  7. @AllArgsConstructor 注解在类,生成包含类中全部字段的构造方法。
  8. @Data 注解在类,为类的全部字段注解@ToString、@EqualsAndHashCode、@Getter的便捷方法,同时为全部非final字段注解@Setter。

lombok的依赖于安装

依赖管理

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

IDEA插件的安装

若是IDE没有安装插件的话会提示错误,并且不会有代码提示,因此IDE要安装插件github

  1. 在IDEA插件里搜索lombok,安装,重启
  2. 直接官网下载插件,安装,这是连接
  3. 设置中启用annotation processors

@Data小例子

平时在使用时最经常使用@Data注解apache

@Data能够很好地处理字段的泛型参数。 为了在为具备泛型的类构造对象时减小样板,可使用staticConstructor参数来生成私有构造函数,以及返回新实例的静态方法。 这样,javac将推断变量名称。 所以,经过这样声明:@Data(staticConstructor =“of”)类Foo {private T x;}能够经过写入来建立Foo的新实例:Foo.of(5); 而没必要写:new Foo (5); 数组

若是使用了@Data注解ide

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

不加lombok注解的Pojo的写法函数

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;
    }
    
    //能够看到这里自动生成了of方法
    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;
    }
  }
}

扩展@ToString

任何类定义均可以用@ToString注释,让lombok生成toString()方法的实现。默认状况下,它会按顺序打印类名以及每一个字段,并以逗号分隔。ui

经过将includeFieldNames参数设置为true,您能够为toString()方法的输出更详细(但也有一些长度)。这是默认的this

默认状况下,将打印全部非静态字段。若是要跳过某些字段,可使用@ ToString.Exclude注释这些字段。或者,您可使用@ToString(onlyExplicitlyIncluded = true)准确指定要使用的字段,而后使用@ ToString.Include标记要包含的每一个字段。编码

经过将callSuper设置为true,能够将toString的超类实现的输出包含到输出中。可是java.lang.Object中toString()的默认实现几乎毫无心义,所以除非扩展另外一个类,不然不要这样作。

还能够在toString中包含方法调用的输出。只能包含不带参数的实例(非静态)方法。为此,请使用@ToString.Include标记方法。

可使用@ToString.Include(name =“some other name”)更改用于标识成员的名称,而且能够经过@ToString.Include(rank = -1)更改为员的打印顺序。没有等级的成员被认为具备等级0,更高等级的成员被首先打印,而且相同等级的成员以它们在源文件中出现的相同顺序被打印。

ToString小例子:

加注解:

@ToString
public class ToStringExample {
  private static final int STATIC_VAR = 10;
  private String name;
  private Shape shape = new Square(5, 10);
  private String[] tags;
  @ToString.Exclude private int id;
  
  public String getName() {
    return this.name;
  }
  
  @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;
    }
  }
}

等效于:

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

构造器注解扩展

@NoArgsConstructor

此注释主要与@Data或生成注释的其余构造函数组合使用。

@NoArgsConstructor将生成一个没有参数的构造函数。若是这是不可能的(由于最终字段),将致使编译器错误,除非使用@NoArgsConstructor(force = true),而后使用0 / false / null初始化全部final字段。对于具备约束的字段,例如@NonNull字段,不会生成任何检查,所以请注意,在稍后正确初始化这些字段以前,一般不会知足这些约束。某些java构造(例如hibernate和Service Provider Interface)须要no-args构造函数。

@RequiredArgsConstructor

@RequiredArgsConstructor为每一个须要特殊处理的字段生成一个带有1个参数的构造函数。全部未初始化的final字段都会得到一个参数,以及标记为@NonNull的任何字段,这些字段在声明它们时未初始化。对于标有@NonNull的字段,还会生成显式空检查。若是用于标记为@NonNull的字段的任何参数包含null,则构造函数将抛出NullPointerException。参数的顺序与字段在类中的显示顺序相匹配。

@AllArgsConstructor

@AllArgsConstructor为类中的每一个字段生成一个带有1个参数的构造函数。标有@NonNull的字段会致使对这些参数进行空检查。

这些注释中的每个都容许使用替代形式,其中生成的构造函数始终是私有的,而且生成包围私有构造函数的附加静态工厂方法。经过为注释提供staticName值来启用此模式,以下所示:@RequiredArgsConstructor(staticName =“of”)。与普通构造函数不一样,这种静态工厂方法将推断泛型。这意味着您的API用户能够编写MapEntry.of(“foo”,5)而不是更长的新MapEntry <String,Integer>(“foo”,5)。

与大多数其余lombok注释不一样,显式构造函数的存在不会阻止这些注解生成本身的构造函数。这意味着能够编写本身的专用构造函数,并让lombok生成样板文件。

注意:若是出现冲突(自定义的一个构造函数最终使用与lombok生成的构造函数相同),则会发生编译器错误

@Log及其余日志注解

就是简化了生成log的代码,直接看例子

@Log
public class LogExample {
  
  public static void main(String... args) {
    log.severe("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.severe("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");
  }
}

资料连接

想要更详细的了解Lombok,推荐查看它的github来阅读更多的使用特性

Lombok的gitHub连接

相关文章
相关标签/搜索