今天为大家推荐一个java的开发神器lombok,可以帮助大家节省开发时间,提升工(mo)作(yu)效(shi)率(jian)。

一、基本介绍

Lombok是一款Java开发插件,可以通过它定义的注解来精简冗长和繁琐的代码,主要针对简单的Java模型对象(POJO)。

好处就显而易见了,可以节省大量重复工作,特别是当POJO类的属性增减时,需要重复修改的Getter/Setter、构造器方法、equals方法和toString方法等。

而且Lombok针对这些内容的处理是在编译期,而不是通过反射机制,这样的好处是并不会降低系统的性能。

目前Lombok已经支持JDK14和JDK13的一些特性

二、IDE安装Lombok开发工具

Lombok的官网中详细的介绍了各种IDE安装Lombok的方法,目前已经指出IDEA、Eclipse、Netbeans、Myeclipse、Spring boot Suite、Visual Studio Code等工具,本文以IDEA为例,介绍安装的方法,其他IDE的安装方法按照官网的方式进行安装。

2.1 在线安装

  1. 点击File -> Settings -> Plugins
  2. 在marketplace中搜索Lombok Lombok
  3. 点击install 安装完成
  4. Restart IntelliJ IDEA 重新IDEA之后

2.2 离线安装

在一些管理比较严格的公司里,开发环境不允许连接外网,离线安装的方法主要方便这些苦难的兄弟
1.进入jetbrains官网,找到Lombook插件
2.根据自己IDEA版本选择对应的版本



idea mongodb离线驱动下载 idea离线安装lombok插件_lombok插件安装

Lombok插件版本选择

  1. 点击File -> Settings -> Plugins,选择install plugins from disk image.png

4.选择下载的插件,后续与在线安装过程一致

注意:选择下载插件时,一定要与IDEA的版本一致,如不一致,会提示不可用,或者安装失败

三、引入依赖

Lombok的官网中分别介绍了maven、gradle、ant和Kobalt四种构建工具如何引入Lombok,本文以maven为例进行简单的介绍,其他构建工具可以参考官网的文档

1<dependencies>
2    <dependency>
3        <groupId>org.projectlombokgroupId>
4        <artifactId>lombokartifactId>
5        <version>1.18.12version>
6        <scope>providedscope>
7    dependency>
8dependencies>

其中,1.18.12版本为当前最新版本,provided表示编译时不会将其打包war/jar包中。

四、注解简介

Lombok的所有注解可以通过官网Lombok features查看

4.1 @Getter/@Setter

这两个注意应该是使用lombok中最常用的的两个注解,一个属性foo,通过@Getter注解生成的get方法的方法名为getFoo(),如果该属性为boolean,则方法名为isFoo();set方法名为setFoo,返回值为void。

@Setter/@Getter生成的方法为public,如果想要修改方法的访问修饰符,可以使用AccessLevel进行限制,AccessLevel支持所有的访问修饰符(PUBLIC、PROTECTED、PACKAGE、PRIVATE)

1@Setter(AccessLevel.PROTECTED) private String name;

官网示例:
Lombok版本

1import lombok.AccessLevel;
 2import lombok.Getter;
 3import lombok.Setter;
 4
 5public class GetterSetterExample {
 6  /** 7   * Age of the person. Water is wet. 8   *  9   * @param age New value for this person's age. Sky is blue.10   * @return The current value of this person's age. Circles are round.11   */
12  @Getter @Setter private int age = 10;
13
14  /**15   * Name of the person.16   * -- SETTER --17   * Changes the name of this person.18   * 19   * @param name The new value.20   */
21  @Setter(AccessLevel.PROTECTED) private String name;
22
23  @Override public String toString() {
24    return String.format("%s (age: %d)", name, age);
25  }
26}

不使用Lombok的程序

1public class GetterSetterExample {
 2  /** 3   * Age of the person. Water is wet. 4   */
 5  private int age = 10;
 6
 7  /** 8   * Name of the person. 9   */
10  private String name;
11
12  @Override public String toString() {
13    return String.format("%s (age: %d)", name, age);
14  }
15
16  /**17   * Age of the person. Water is wet.18   *19   * @return The current value of this person's age. Circles are round.20   */
21  public int getAge() {
22    return age;
23  }
24
25  /**26   * Age of the person. Water is wet.27   *28   * @param age New value for this person's age. Sky is blue.29   */
30  public void setAge(int age) {
31    this.age = age;
32  }
33
34  /**35   * Changes the name of this person.36   *37   * @param name The new value.38   */
39  protected void setName(String name) {
40    this.name = name;
41  }
42}

示例中的@Setter@Getter注解分别放到了具体的属性前,在开发过程中,通常直接放到类的定义前,这样表示该类中的所有属性都要生成set/get方法

4.2 @NonNull

作用于属性上,提供关于此参数的非空检查,如果参数为空,则抛出空指针异常。
非空检查的代码示例如下:

1if (param == null) 
2    throw new NullPointerException("param is marked @NonNull but is null")

官方示例:
Lombok版本

1public class NonNullExample extends Something {
2  private String name;
3
4  public NonNullExample(@NonNull Person person) {
5    super("Hello");
6    this.name = person.getName();
7  }
8}

不带Lombok版本

1public class NonNullExample extends Something {
 2  private String name;
 3
 4  public NonNullExample(Person person) {
 5    super("Hello");
 6    if (person == null) {
 7      throw new NullPointerException("person is marked @NonNull but is null");
 8    }
 9    this.name = person.getName();
10  }
11}

注意:官网中Vanilla Java版本中在Person person前增加了@NonNull 注解,应该是编写错误,此处特意进行说明

4.3 @NoArgsConstructor/@RequiredArgsConstructor/@AllArgsConstructor

这三个注解主要是生成构造函数的标签,其中:@NoArgsConstructor表示生成一个不带参数的构造方法;@RequiredArgsConstructor表示生成一些特定属性的构造方法,特定参数包括final的字段和标记@NonNull的字段;使用该标签生成的构造方法的访问修饰符为private,可以增加staticName属性值,该属性默认为“”,增加该属性后,会默认生成一个名为staticName值的构造方法,其访问修饰符为public的静态方法,参数与@RequiredArgsConstructor参数一致@AllArgsConstructor表示生成所有属性的构造方法;

官方示例:
Lombok版本

1import lombok.AccessLevel;
 2import lombok.RequiredArgsConstructor;
 3import lombok.AllArgsConstructor;
 4import lombok.NonNull;
 5
 6@RequiredArgsConstructor(staticName = "of")
 7@AllArgsConstructor(access = AccessLevel.PROTECTED)
 8@NoArgsConstructor
 9public class ConstructorExample<T> {
10  private int x, y;
11  @NonNull private T description;
12}

不带Lombok版本

1public class ConstructorExample<T> {
 2  private int x, y;
 3  @NonNull private T description;
 4}
 5
 6// @NoArgsConstructor对应的构造方法
 7private ConstructorExample(T description) {
 8
 9}
10// @RequiredArgsConstructor对应的构造方法
11private ConstructorExample(T description) {
12    if (description == null) throw new NullPointerException("description");
13    this.description = description;
14  }
15
16// 增加staticName后生成的构造方法
17 public static  ConstructorExample of(T description) {18    return new ConstructorExample(description);19 }2021// @AllArgsConstructor对应的构造方法22  @java.beans.ConstructorProperties({"x", "y", "description"})23protected ConstructorExample(int x, int y, T description) {24    if (description == null) throw new NullPointerException("description");25    this.x = x;26    this.y = y;27    this.description = description;28 }

官方给出的示例让人看起来有点摸不着头脑,为了方便清楚的明白这三个标签,将官方的示例进行调整,效果可能会更好一点。

查看使用三个注解生成的方法,与不使用Lombok的构造方法完全一致



idea mongodb离线驱动下载 idea离线安装lombok插件_lombok插件安装_02

IDEA 类方法结构

4.4 @ToString

@ToString自动生成一个toString()方法,默认情况是所有的字段都在进行字符串输出,当然,可以使用@ToString.Exclude的方式排除一些字段不显示输出。

4.5@Data

@Data注解集成了@ToString@EqualsAndHashCode@Getter / @Setter@RequiredArgsConstructor

4.6 @EqualsAndHashCode

@EqualsAndHashCode生成hashCode()canEqualequals()方法

4.7 val/var

使用val作为局部变量声明的类型,而不是实际写入类型。执行此操作时,将从初始化表达式推断出类型。varval几乎一样,只是变量前没有final的定义

我理解var和val与javascript中的左右几乎相同,在对变量赋值之后在进行赋值,这两个属性不是注解,是一个类,实际场景中可能的用途不是太多

官方示例:
Lombok版本

1import java.util.ArrayList;
 2import java.util.HashMap;
 3import lombok.val;
 4
 5public class ValExample {
 6  public String example() {
 7    val example = new ArrayList(); 8    example.add("Hello, World!"); 9    val foo = example.get(0);10    return foo.toLowerCase();11  }12}

不带Lombok版本

1import java.util.ArrayList;
 2import java.util.HashMap;
 3import java.util.Map;
 4
 5public class ValExample {
 6  public String example() {
 7    final ArrayList example = new ArrayList(); 8    example.add("Hello, World!"); 9    final String foo = example.get(0);10    return foo.toLowerCase();11  }12}

其他的属性可以参考官网中稳定版本的特性列表,不在额外叙述

五、关于Lombok的一些争议

之前在网上有人发布Lombok是让你代码处于“亚健康”状态的真正元凶,提出Lombok存在的四个问题:

1    * JDK8升级到JDK11后,Lombok不能使用
2    * 胁迫使用:当你的源代码中使用了Lombok,恰好你的代码又被其他的人所使用,那么依赖你代码的人,也必须安装Lombok插件
3    * 可读性差:Lombok隐藏了JavaBean封装的细节,所有JavaBean中的方法你只能想象他们长什么样子,你并不能看见
4    * 代码耦合度增加:当你使用Lombok来编写某一个模块的代码后,其余依赖此模块的其他代码都需要引入Lombok依赖,同时还需要在IDE中安装Lombok的插件,这是一种入侵式的耦合

关于第一个问题,其实是Lombok的版本原因,在项目中使用了相对较低的版本,会存在升级JDK后不能使用的问题,升级到最新的Lombok就可,那会不会有有问题呢?呵呵呵,JDK都升级了还怕插件升级有问题吗?

关于第二点,的确是不可避免的事实,既然都是使用到代码级别,那应该是一个团队或者一个公司级别,换一个思路思考,那团队或者公司要求使用相同的架构和框架是不是也很合理?

关于第三个问题,实际上可以适当的选择Lombok的注解,对于不好用的注解可以选择不使用。在我看来,@Getter@Setter就可以解决我大量的工作

关于第四个问题,实际上可以使用maven的配置就可以解决相关问题,可以增加true,这样依赖可以不传给引用的项目。