lombok

Lombok简介

Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法。官方地址:https://projectlombok.org/,github地址:https://github.com/rzwitserloot/lombok

IntelliJ IDEA 使用它的方法

  • 先安装插件
Paste_Image.png
  • 然后引入lombok的jar包
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.14</version>
</dependency>

注解的介绍

官方注解介绍

  • @Getter and @Setter

    你可以用@Getter / @Setter注释任何字段(当然也可以注释到类上的),让lombok自动生成默认的getter / setter方法。
    默认生成的方法是public的,如果要修改方法修饰符可以设置AccessLevel的值,例如:@Getter(access = AccessLevel.PROTECTED)

Paste_Image.png
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
public class User {
    @Getter(AccessLevel.PROTECTED) @Setter private Integer id;
    @Getter @Setter private String name;
    @Getter @Setter private String phone;
}
  • @ToString

    生成toString()方法,默认情况下,它会按顺序(以逗号分隔)打印你的类名称以及每个字段。可以这样设置不包含哪些字段@ToString(exclude = "id") / @ToString(exclude = {"id","name"})
    如果继承的有父类的话,可以设置callSuper 让其调用父类的toString()方法,例如:@ToString(callSuper = true)

import lombok.ToString;
@ToString(exclude = {"id","name"})
public class User {
  private Integer id;
  private String name;
  private String phone;
}

生成toString方法如下:

public String toString(){
  return "User(phone=" + phone + ")";
}
  • @EqualsAndHashCode

    生成hashCode()和equals()方法,默认情况下,它将使用所有非静态,非transient字段。但可以通过在可选的exclude参数中来排除更多字段。或者,通过在parameter参数中命名它们来准确指定希望使用哪些字段。

@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 transient 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 transient 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;
   }
 }
}
  • @NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor

    @NoArgsConstructor生成一个无参构造方法。当类中有final字段没有被初始化时,编译器会报错,此时可用@NoArgsConstructor(force = true),然后就会为没有初始化的final字段设置默认值 0 / false / null。对于具有约束的字段(例如@NonNull字段),不会生成检查或分配,因此请注意,正确初始化这些字段之前,这些约束无效。

import lombok.NoArgsConstructor;
import lombok.NonNull;
@NoArgsConstructor(force = true)
public class User {
    @NonNull private Integer id;
    @NonNull private String name;
    private final String phone ;
}

@RequiredArgsConstructor会生成构造方法(可能带参数也可能不带参数),如果带参数,这参数只能是以final修饰的未经初始化的字段,或者是以@NonNull注解的未经初始化的字段
@RequiredArgsConstructor(staticName = "of")会生成一个of()的静态方法,并把构造方法设置为私有的

Paste_Image.png

Paste_Image.png
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class User {
  @NonNull private Integer id ;
  @NonNull private String name = "bbbb";
  private final String phone;
}
//另外一个
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor(staticName = "of")
public class User {
  @NonNull private Integer id ;
  @NonNull private String name = "bbbb";
  private final String phone;
}

@AllArgsConstructor 生成一个全参数的构造方法

Paste_Image.png
import lombok.AllArgsConstructor;
import lombok.NonNull;
@AllArgsConstructor
public class User {
  @NonNull private Integer id ;
  @NonNull private String name = "bbbb";
  private final String phone;
}
  • @Data

    @Data 包含了 @ToString、@EqualsAndHashCode、@Getter / @Setter和@RequiredArgsConstructor的功能

  • @Accessors

    @Accessors 主要用于控制生成的getter和setter
    主要参数介绍

    • fluent boolean值,默认为false。此字段主要为控制生成的getter和setter方法前面是否带get/set
    • chain boolean值,默认false。如果设置为true,setter返回的是此对象,方便链式调用方法
    • prefix 设置前缀 例如:@Accessors(prefix = "abc") private String abcAge 当生成get/set方法时,会把此前缀去掉
    Paste_Image.png
  • @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");
  }
}
}
  • @Wither

    提供了给final字段赋值的一种方法

//使用lombok注解的
import lombok.AccessLevel;
import lombok.NonNull;
import lombok.experimental.Wither;
public class WitherExample {
  @Wither private final int age;
  @Wither(AccessLevel.PROTECTED) @NonNull private final String name;
   
  public WitherExample(String name, int age) {
    if (name == null) throw new NullPointerException();
    this.name = name;
    this.age = age;
  }
}
//等效代码
import lombok.NonNull;
public class WitherExample {
private final int age;
private @NonNull final String name;

public WitherExample(String name, int age) {
 if (name == null) throw new NullPointerException();
 this.name = name;
 this.age = age;
}

public WitherExample withAge(int age) {
 return this.age == age ? this : new WitherExample(age, name);
}

protected WitherExample withName(@NonNull String name) {
 if (name == null) throw new java.lang.NullPointerException("name");
 return this.name == name ? this : new WitherExample(age, name);
}
}
  • @onX

    在注解里面添加注解的方式

直接看代码

public class SchoolDownloadLimit implements Serializable {
    private static final long serialVersionUID = -196412797757026250L;

    @Getter(onMethod = @_({@Id,@Column(name="id",nullable=false),@GeneratedValue(strategy= GenerationType.AUTO)}))
    @Setter
    private Integer id;

    @Getter(onMethod = @_(@Column(name="school_id")))
    @Setter
    private Integer schoolId;


    @Getter(onMethod = @_(@Column(name = "per_download_times")))
    @Setter
    private Integer perDownloadTimes;

    @Getter(onMethod = @_(@Column(name = "limit_time")))
    @Setter
    private Integer limitTime;

    @Getter(onMethod = @_(@Column(name = "download_to_limit_an_hour")))
    @Setter
    private Integer downloadToLimitInHour;

    @Getter(onMethod = @_(@Column(name = "available")))
    @Setter
    private Integer available = 1;
}
  • @Builder

    @Builder注释为你的类生成复杂的构建器API。
    lets you automatically produce the code required to have your class be instantiable with code such as:

Person.builder().name("Adam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build();

直接看官方示例,对比一下就都明白了

//使用lombok注解的
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;
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 + ")";
      }
  }
}
  • @Delegate

    这个注解也是相当的牛逼,看下面的截图,它会该类生成一些列的方法,这些方法都来自与List接口

    Paste_Image.png

附带一个我使用的例子
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.Date;

@Entity
@Table(name= Constants.TABLE_SCHOOL_DOWNLOAD_LIMIT)
@RequiredArgsConstructor(staticName = "of")
@Accessors(chain = true)
@ToString
public class SchoolDownloadLimit implements Serializable {
    private static final long serialVersionUID = -196412797757026250L;

    @Getter(onMethod = @_({@Id,@Column(name="id",nullable=false),@GeneratedValue(strategy= GenerationType.AUTO)}))
    @Setter
    private Integer id;

    @Getter(onMethod = @_(@Column(name="school_id")))
    @Setter
    private Integer schoolId;

    @Getter(onMethod = @_(@Column(name = "per_download_times")))
    @Setter
    private Integer perDownloadTimes;

    @Getter(onMethod = @_(@Column(name = "limit_time")))
    @Setter
    private Integer limitTime;

    @Getter(onMethod = @_(@Column(name = "download_to_limit_an_hour")))
    @Setter
    private Integer downloadToLimitInHour;

    @Getter(onMethod = @_(@Column(name = "available")))
    @Setter
    private Integer available = 1;

    @Getter(onMethod = @_(@Column(name = "create_time")))
    @Setter
    private Date createTime;

    @Getter(onMethod = @_(@Column(name = "update_time")))
    @Setter
    private Date updateTime;
}

就介绍这么多了,更多的注解请看官方文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容