前言
Lombok是一个作用于编辑器和构建工具的 Java 库,可以对编写的 Java 代码进行增强,比如说不用再写实体类的 getter 方法,equals 方法而是自动生成,自动生成日志输出变量等等,减少重复模板的代码。
常用注解介绍
@Getter/@Setter
在我们编写实体类的时候无论多少个属性,都要为其提供 getter 和 setter 方法,如果属性过多就会显得代码过于臃肿,这个时候可以使用@Getter/@Setter来代替 getter 和 setter 方法。如下所示:
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class LombokEntity {
private String value;
}
@NonNull
@NonNull 用于标记类中不能允许为 null 的字段或者参数上,任何使用该字段的地方都生成空指针判断代码,若@NonNull 标记的变量为 null,抛出 NullPointException (NPE) 异常。使用方式如下所示:
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
@Setter
@Getter
public class LombokEntity {
private String value;
public LombokEntity(@NonNull String value) {
this.value = value;
}
}
构造器相关注解
Lombok提供了一系列的关于构造器的注解,包括无参构造器和有参构造器。
- @NoArgsConstructor 为实体类生成无参的构造器方法
- @AllArgsConstructor 为实体类生成除了static修饰的字段之外带有各参数的构造器方法。
- @RequiredArgsConstructor 为实体类生成指定字段的构造器方法,而这些字段需要被 final,或者 @NonNull
修饰。
这里只介绍RequiredArgsConstructor 的使用,如下所示:
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@Setter
@Getter
@RequiredArgsConstructor
public class LombokEntity {
private final String value;
}
编译之后创建LombokEntity 的时候,就必须是new LombokEntity(“value”)来创建。
@ToString
@ToString 会给类自动生成易阅读的 toString 方法,带上有所非静态字段的属性名称和值,这样就十分便于我们日常开发时进行的打印操作。
@Setter
@Getter
@RequiredArgsConstructor
@ToString
public class LombokEntity {
private final String value;
}
另外@ToString还支持设置指定哪些字段的日志化输出,哪些不需要出现在 toString 方法中。使用属性 @ToString.Exclude排除不需要在 toString 中出现的字段,使用 @ToString.Include标记需要出现在 toString 中的字段,示例代码如下:
@Setter
@Getter
@RequiredArgsConstructor
@ToString
public class LombokEntity {
@ToString.Exclude
private final String value;
}
@EqualsAndHashCode
@EqualsAndHashCode 注解就是用于根据类所拥有的非静态字段自动重写 equals 方法和 hashCode 方法,方便我们用于对象间的比较。用法和@ToString类似,同样也支持@EqualsAndHashCode.Exclude和@EqualsAndHashCode.Include,使用方式如下:
@Setter
@Getter
@RequiredArgsConstructor
@ToString
@EqualsAndHashCode
public class LombokEntity {
@ToString.Exclude
@EqualsAndHashCode.Exclude
private final String value;
}
@Data/@Value
@Data/@Value 注解,提供了更综合的生成代码功能,等价于下面几个注解。
@see lombok.Getter
@see lombok.experimental.FieldDefaults
@see lombok.AllArgsConstructor
@see lombok.ToString
@see lombok.EqualsAndHashCode
@see lombok.Data
@Builder
@Builder 是一个非常强大的注解,提供了一种基于建造者模式的构建对象的 API。使用 @Builder 注解为给我们的实体类自动生成 builder() 方法,并且直接根据字段名称方法进行字段赋值,最后使用 build()方法构建出一个实体对象。
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class LombokBuilder {
private int id;
private String name;
}
public class TestMain {
public static void main(String[] args) {
LombokBuilder lombokBuilder = LombokBuilder.builder().id(2).build();
}
}
但是 @Builder 不支持父类字段的生成,当一个实体类存在父类时,@Builder 只能生成当前类的字段构建方法。若需要用到父类的字段方法时, Lombok 提供了新的注解 @SuperBuilder 来应对这种情况,下面是 @SuperBuilder 注解的使用方式。
@SuperBuilder
@Data
public class LombokBuilderParent {
private String value;
}
@Data
@SuperBuilder
public class LombokBuilder extends LombokBuilderParent{
private int id;
private String name;
}
日志注解
Lombok也支持了各式各样的日志注解,对应的注解如下:
@CommonsLog 等价效果: private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@Flogger 等价效果: private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();
@JBosLog 等价效果: private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
@Log 等价效果: private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j 等价效果: private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
@Log4j2 等价效果: private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4j 等价效果: private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4j 等价效果: private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
@Cleanup
@Cleanup 用于标记需要释放清理操作的资源对象变量,如 FileInputStream, FileOutputStream 等,标记之后资源对象使用完毕后,就会被自动关闭和清理,实际上这里 Lombok 实现效果与 Java7 特性 try with resource 一样, 为我们屏蔽了关闭资源的模板代码。使用示例如下:
public static void main(String[] args) throws FileNotFoundException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = 0;
try {
r = in.read(b);
} catch (IOException e) {
e.printStackTrace();
}
if (r == -1) {
break;
}
try {
out.write(b, 0, r);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SneakyThrows
@SneakyThrows 主要用于在没有 throws 关键字的情况下,隐蔽地抛出受检查异常,为我们平常开发中需要异常抛出时省去的 throw 操作。
@SneakyThrows
public static void main(String[] args) {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = 0;
try {
r = in.read(b);
} catch (IOException e) {
e.printStackTrace();
}
if (r == -1) {
break;
}
try {
out.write(b, 0, r);
} catch (IOException e) {
e.printStackTrace();
}
}
}
val/var
val/var 用于局部变量的修饰,有了这注解修饰后,变量的类型就会自动通过等号右边的表达式推断出来,这个功能借鉴于许多编程语言的自动类型推断的特性。 而 val 与 var 的区别在于, val 用于修饰不可变变量,var 修饰可变变量。当 val 修饰的变量被重新赋值时,编译器就会提示异常:Error: java: 无法为最终变量 X 分配值。
val str = "abc";
str = "bcd"; //throw Error: java
var count = "test";
count = "test2";