Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.
Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
上面的一段话是 lombok 的官方介绍,lombok 是一个 Java 库,可以自动插入编辑器和构建工具,使 Java 代码简练、快捷。永远告别 setter、getter和equals方法编写。
虽然省去了手动创建getter/setter方法的麻烦,但大大降低了源代码的可读性和完整性,降低了阅读源代码的舒适度
org.projectlombok
lombok
true
在类上添加@Data
注解,会为类的所有属性自动生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。如下,UserInfo类只有属性的定义,并不用写setter/getter等方法。
@Data
@Document(collection = "USER_INFO") //用户信息表
public class UserInfo extends CommonField implements Serializable {
private static final long serialVersionUID = -7898194272883238670L;
private static final String OBJECT_KEY = "USERINFO";
@Field("USER_NUM")
private String userNum; //用户帐号
@Field("USER_PASSWORD")
private String userPassword; //用户密码
@Field("USER_NAME")
private String userName; //用户姓名
public String getKey() { //获取 Redis 存储键名
return this.userNum;
}
public String getObjectKey() { //Redis 存储块名
return OBJECT_KEY;
}
}
如果感觉@Data
注解的范围过大,可以使用以下注解:
自动生成 getter 方法
@Getter
private String userName; //用户姓名
自动生成 setter 方法
@Setter
private String userName; //用户姓名
该注解用在属性或构造器上,Lombok会生成一个非空的声明,可用于校验参数,能帮助避免空指针。
使用前:
import lombok.NonNull;
public class NonNullExample extends Something {
private String name;
public NonNullExample(@NonNull Person person) {
super("Hello");
if (person == null) {
throw new NullPointerException("person");
}
this.name = person.getName();
}
}
使用后:
import lombok.NonNull;
public class NonNullExample extends Something {
private String name;
public NonNullExample(@NonNull Person person) {
super("Hello");
this.name = person.getName();
}
}
自动调用close()方法
使用前:
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(args[0]);
try {
OutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
if (out != null) {
out.close();
}
}
} finally {
if (in != null) {
in.close();
}
}
}
}
使用后:
import lombok.Cleanup;
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
}
默认情况下,会使用所有非静态(non-static)和非瞬态(non-transient)属性来生成 equals 和 hasCode,也能通过 exclude 注解来排除一些属性。如果使用的类继承了某个父类,默认是不会包含父类属性的,可以通过添加 callSuper=true 来包含父类的属性。
import lombok.EqualsAndHashCode;
@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 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;
}
}
类使用 @ToString 注解,Lombok 会生成一个 toString() 方法,默认情况下,会输出类名、所有属性(会按照属性定义顺序),用逗号来分割。通过将 includeFieldNames 参数设为 true,就能明确的输出 toString() 属性。添加 callSuper=true 来包含父类的属性。
使用前:
import java.util.Arrays;
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) + ")";
}
}
使用后:
import lombok.ToString;
@ToString(exclude="id")
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();
}
@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 ConstructorExample {
private int x, y;
@NonNull private T description;
private ConstructorExample(T description) {
if (description == null) throw new NullPointerException("description");
this.description = description;
}
public static ConstructorExample of(T description) {
return new ConstructorExample(description);
}
@java.beans.ConstructorProperties({"x", "y", "description"})
protected ConstructorExample(int x, int y, T description) {
if (description == null) throw new NullPointerException("description");
this.x = x;
this.y = y;
this.description = description;
}
public static class NoArgsExample {
@NonNull private String field;
public NoArgsExample() {
}
}
}
使用后:
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.NonNull;
@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class ConstructorExample {
private int x, y;
@NonNull private T description;
@NoArgsConstructor
public static class NoArgsExample {
@NonNull private String field;
}
}
实际开发中,我们会把实体类中相同的字段(如:ID、创建时间等)提取出来,创建实体类的时候只需要继承基类就可以了,这种情况下就会产生很多继承了基类的实体类,lombok 的 @EqualsAndHashCode 默认不包含父类属性,那么我们需要在每个实体类中都要设置 callSuper=true,这样写起来会大大增加代码量。这时候就需要统一配置了,lombok 提供了在配置文件中统一配置的方法。
lombok 的配置文件对同目录及同级目录下的所有子目录有效,优先级采取就近原则,例如:子目录下配置文件的优先级高于根目录下配置文件的优先级
创建配置文件lombok.config
# 指定lombok根目录
config.stopBubbling=true
# lombok 默认子类的 equals 和 hashCode 方法,不会包含或者考虑基类的属性。
# 添加如下配置即可包含父类属性。
lombok.equalsAndHashCode.callSuper=call