Lombok 天宇轩

Lombok 简介

Lombok 是一种 Java 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO)。它通过注释实现这一目的。通过在开发环境中实现 Lombok,开发人员可以节省构建诸如 hashCode()equals()getter / setter 这样的方法以及以往用来分类各种 accessor 和 mutator 的大量时间。

Lombok 安装

使 IntelliJ IDEA 支持 Lombok 方式如下:

  • Intellij 设置支持注解处理

    点击 File > Settings > Build > Annotation Processors

    勾选 Enable annotation processing

  • 安装插件

    点击 Settings > Plugins > Browse repositories

    查找 Lombok Plugin 并进行安装

    重启 IntelliJ IDEA

  • 将 lombok 添加到 pom 文件

 <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
            <scope>provided</scope>
        </dependency>

  

Lombok 使用

官网API

Lombok 提供注解API 来修饰指定的类:

@Getter and @Setter

@Getter and @Setter Lombok 代码:

@Getter @Setter 
private boolean employed = true;
@Setter(AccessLevel.PROTECTED) 
private String name;
等价于 Java 源码:

private boolean employed = true;
private String name;
​
public boolean isEmployed() {
    return employed;
}
​
public void setEmployed(final boolean employed) {
    this.employed = employed;
}
​
protected void setName(final String name) {
    this.name = name;
}

  

@NonNull

@NonNull Lombok 代码:

@Getter @Setter @NonNull
private List<Person> members;
等价于 Java 源码:

@NonNull
private List<Person> members;
​
public Family(@NonNull final List<Person> members) {
    if (members == null) throw new java.lang.NullPointerException("members");
    this.members = members;
}
    
@NonNull
public List<Person> getMembers() {
    return members;
}
​
public void setMembers(@NonNull final List<Person> members) {
    if (members == null) throw new java.lang.NullPointerException("members");
    this.members = members;
}

  

@ToString

@ToString Lombok 代码:

@ToString(callSuper=true,exclude="someExcludedField")
public class Foo extends Bar {
    private boolean someBoolean = true;
    private String someStringField;
    private float someExcludedField;
}
等价于 Java 源码:

public class Foo extends Bar {
    private boolean someBoolean = true;
    private String someStringField;
    private float someExcludedField;
    
    @java.lang.Override
    public java.lang.String toString() {
        return "Foo(super=" + super.toString() +
            ", someBoolean=" + someBoolean +
            ", someStringField=" + someStringField + ")";
    }
}

  

@EqualsAndHashCode

@EqualsAndHashCode Lombok 代码:

@EqualsAndHashCode(callSuper=true,exclude={"address","city","state","zip"})
public class Person extends SentientBeing {
    enum Gender { Male, Female }
​
    @NonNull private String name;
    @NonNull private Gender gender;
    
    private String ssn;
    private String address;
    private String city;
    private String state;
    private String zip;
}
等价于 Java 源码:

public class Person extends SentientBeing {
    
    enum Gender {
        /*public static final*/ Male /* = new Gender() */,
        /*public static final*/ Female /* = new Gender() */;
    }
    @NonNull
    private String name;
    @NonNull
    private Gender gender;
    private String ssn;
    private String address;
    private String city;
    private String state;
    private String zip;
    
    @java.lang.Override
    public boolean equals(final java.lang.Object o) {
        if (o == this) return true;
        if (o == null) return false;
        if (o.getClass() != this.getClass()) return false;
        if (!super.equals(o)) return false;
        final Person other = (Person)o;
        if (this.name == null ? other.name != null : !this.name.equals(other.name)) return false;
        if (this.gender == null ? other.gender != null : !this.gender.equals(other.gender)) return false;
        if (this.ssn == null ? other.ssn != null : !this.ssn.equals(other.ssn)) return false;
        return true;
    }
    
    @java.lang.Override
    public int hashCode() {
        final int PRIME = 31;
        int result = 1;
        result = result * PRIME + super.hashCode();
        result = result * PRIME + (this.name == null ? 0 : this.name.hashCode());
        result = result * PRIME + (this.gender == null ? 0 : this.gender.hashCode());
        result = result * PRIME + (this.ssn == null ? 0 : this.ssn.hashCode());
        return result;
    }
}

@Data

@Data Lombok 代码:

@Data(staticConstructor="of")
public class Company {
    private final Person founder;
    private String name;
    private List<Person> employees;
}
等价于 Java 源码:

public class Company {
    private final Person founder;
    private String name;
    private List<Person> employees;
    
    private Company(final Person founder) {
        this.founder = founder;
    }
    
    public static Company of(final Person founder) {
        return new Company(founder);
    }
    
    public Person getFounder() {
        return founder;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(final String name) {
        this.name = name;
    }
    
    public List<Person> getEmployees() {
        return employees;
    }
    
    public void setEmployees(final List<Person> employees) {
        this.employees = employees;
    }
    
    @java.lang.Override
    public boolean equals(final java.lang.Object o) {
        if (o == this) return true;
        if (o == null) return false;
        if (o.getClass() != this.getClass()) return false;
        final Company other = (Company)o;
        if (this.founder == null ? other.founder != null : !this.founder.equals(other.founder)) return false;
        if (this.name == null ? other.name != null : !this.name.equals(other.name)) return false;
        if (this.employees == null ? other.employees != null : !this.employees.equals(other.employees)) return false;
        return true;
    }
    
    @java.lang.Override
    public int hashCode() {
        final int PRIME = 31;
        int result = 1;
        result = result * PRIME + (this.founder == null ? 0 : this.founder.hashCode());
        result = result * PRIME + (this.name == null ? 0 : this.name.hashCode());
        result = result * PRIME + (this.employees == null ? 0 : this.employees.hashCode());
        return result;
    }
    
    @java.lang.Override
    public java.lang.String toString() {
        return "Company(founder=" + founder + ", name=" + name + ", employees=" + employees + ")";
    }
}
所有属性的get和set方法
toString 方法
hashCode方法
equals方法

  

@Cleanup

@Cleanup Lombok 代码:

public void testCleanUp() {
    try {
        @Cleanup ByteArrayOutputStream baos = new ByteArrayOutputStream();
        baos.write(new byte[] {'Y','e','s'});
        System.out.println(baos.toString());
    } catch (IOException e) {
        e.printStackTrace();
    }
}
等价于 Java 源码:

public void testCleanUp() {
    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            baos.write(new byte[]{'Y', 'e', 's'});
            System.out.println(baos.toString());
        } finally {
            baos.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

  

@Synchronized

@Synchronized Lombok 代码:

private DateFormat format = new SimpleDateFormat("MM-dd-YYYY");
​
@Synchronized
public String synchronizedFormat(Date date) {
    return format.format(date);
}
等价于 Java 源码:

private final java.lang.Object $lock = new java.lang.Object[0];
private DateFormat format = new SimpleDateFormat("MM-dd-YYYY");
​
public String synchronizedFormat(Date date) {
    synchronized ($lock) {
        return format.format(date);
    }
}

  

@SneakyThrows

@SneakyThrows Lombok 代码:

@SneakyThrows
public void testSneakyThrows() {
    throw new IllegalAccessException();
}
Exception in thread "main" java.lang.IllegalAccessException
    at com.topcheer.springboot01.Test.main(Test.java:15)
等价于 Java 源码:

public void testSneakyThrows() {
    try {
        throw new IllegalAccessException();
    } catch (java.lang.Throwable $ex) {
        throw lombok.Lombok.sneakyThrow($ex);
    }
}
java.lang.IllegalAccessException
    at com.topcheer.springboot01.Test.main(Test.java:13)
示例
使用 Lombok 定义一个 Java Bean

import lombok.Data;
import lombok.ToString;
​
@Data
@ToString(exclude = "age")
public class Person {
    private String name;
    private Integer age;
    private String sex;
}
测试

Person person = new Person();
person.setName("张三");
person.setAge(20);
person.setSex("男");
System.out.println(person.toString());
// output: Person(name=张三, sex=男)

  

其他说明

@AllArgsConstructor
这个注解是所有的参数构造器
@NoArgsConstructor
无参构造
@RequiredArgsConstructor
为每个需要特殊处理的字段生成一个带有1个参数的构造函数,且生成的构造为私有,需要通过设置 staticName 来获取访问;
@RequiredArgsConstructor
功能
​
生成一个包含必填参数的构造函数
​
注意
​
要与@NonNull 搭配使用,该注解修饰的属性就是必填参数
​
源码
​
@RequiredArgsConstructor
public class LombokDemo {
​
  @NonNull private Integer id;
  private String name;
}
​
编译后
​
package xyz.mrwood.study.lombok;
​
import java.beans.ConstructorProperties;
import lombok.NonNull;
​
public class LombokDemo {
  @NonNull
  private Integer id;
  private String name;
​
  @ConstructorProperties({"id"})
  public LombokDemo(@NonNull Integer id) {
      if(id == null) {
          throw new NullPointerException("id");
      } else {
          this.id = id;
      }
  }
}
 

@NoAragsConstructor
功能
​
添加一个无参构造函数
​
注意
​
这个注解在没有其它有参构造函数的情况下使用意义不大,因为在这种情况下java默认会添加一个无参构造函数
​
源码
​
@NoArgsConstructor
public class LombokDemo {
​
  private Integer id;
  private String name;
}
​
编译后
​
package xyz.mrwood.study.lombok;
​
public class LombokDemo {
  private Integer id;
  private String name;
​
  public LombokDemo() {
  }
}
​
​
@AllArgsConstructor
功能
​
添加一个所有参数的构造函数
​
源码
​
@AllArgsConstructor
public class LombokDemo {
​
  private Integer id;
  private String name;
}
编译后
​
package xyz.mrwood.study.lombok;
​
import java.beans.ConstructorProperties;
​
public class LombokDemo {
  private Integer id;
  private String name;
​
  @ConstructorProperties({"id", "name"})
  public LombokDemo(Integer id, String name) {
      this.id = id;
      this.name = name;
  }
}

  

@Value

@Value
功能
​
不可变类的@Date, 他会默认给属性加上final
​
源码
​
@Value
public class LombokDemo {
​
  private Integer id;
  private String name;
}
​
编译后
​
package xyz.mrwood.study.lombok;
​
import java.beans.ConstructorProperties;
​
public final class LombokDemo {
  private final Integer id;
  private final String name;
​
  @ConstructorProperties({"id", "name"})
  public LombokDemo(Integer id, String name) {
      this.id = id;
      this.name = name;
  }
​
  public Integer getId() {
      return this.id;
  }
​
  public String getName() {
      return this.name;
  }
​
  public boolean equals(Object o) {
      if(o == this) {
          return true;
      } else if(!(o instanceof LombokDemo)) {
          return false;
      } else {
          LombokDemo other = (LombokDemo)o;
          Integer this$id = this.getId();
          Integer other$id = other.getId();
          if(this$id == null) {
              if(other$id != null) {
                  return false;
              }
          } else if(!this$id.equals(other$id)) {
              return false;
          }
​
          String this$name = this.getName();
          String other$name = other.getName();
          if(this$name == null) {
              if(other$name != null) {
                  return false;
              }
          } else if(!this$name.equals(other$name)) {
              return false;
          }
​
          return true;
      }
  }
​
  public int hashCode() {
      boolean PRIME = true;
      byte result = 1;
      Integer $id = this.getId();
      int result1 = result * 59 + ($id == null?43:$id.hashCode());
      String $name = this.getName();
      result1 = result1 * 59 + ($name == null?43:$name.hashCode());
      return result1;
  }
​
  public String toString() {
      return "LombokDemo(id=" + this.getId() + ", name=" + this.getName() + ")";
  }
}

 

@Builder

注解提供了一种比较推崇的构建值对象的方式

Dog dog = Dog.builder().age(12).name("大黄").build();
System.out.println(dog);
//Dog(name=大黄, age=12)
但是的确很有创意,这些注解已经在jar中提供,只不过它是归在”lombok.experimental.” 包中;而基本功能在”lombok.” 包中。

@Builder.Default
    private  Boolean flag = false;
//Dog(name=大黄, age=12, flag=false) 初始化的时候会把值带进去,适合有默认值的

@Accessors 定制流畅的访问器。

@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) {
    User user=new User().setAge(31).setName("pollyduan");
    System.out.println(user);
}
@Accessors(fluent = true)
与chain=true类似,区别在于getter和setter不带set和get前缀。

  

 

@val @var

使用Lombok ,java也能够像javascript一样使用弱类型定义变量了

val注解变量申明是final类型 var注解变量是非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());  
    }  
  }  
}  
翻译后

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

  

 

@UtilityClass

功能

把普通类转为工具类

源码

  @UtilityClass
  public class LombokDemo {

      private Integer id = 1;
      private String name = "kiwi";

      public void util(){

          System.out.println("xxx");
      }
  }

编译后

package xyz.mrwood.study.lombok;

public final class LombokDemo {
  private static Integer id = Integer.valueOf(1);
  private static String name = "kiwi";

  public static void util() {
      System.out.println("xxx");
  }

  private LombokDemo() {
      throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
  }
}

  

资料

Lombok 官网 | Lombok Github

IntelliJ IDEA - Lombok Plugin

原文地址:https://www.cnblogs.com/dalianpai/p/11656094.html