Lombok 是一种 Java 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO)。它通过注释实现这一目的。通过在开发环境中实现 Lombok,开发人员可以节省构建诸如 hashCode() 和 equals() 、getter / setter 这样的方法以及以往用来分类各种 accessor 和 mutator 的大量时间。
使 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 来修饰指定的类:
@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 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 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 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 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 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 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 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
功能
?
不可变类的@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() + ")";
}
}
注解提供了一种比较推崇的构建值对象的方式
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(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前缀。
使用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
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");
}
}
原文:https://www.cnblogs.com/dalianpai/p/11656094.html