1、概述
1.1 什么是 Lombok?
Lombok:是一个 Java 库,它可以通过注解的方式自动生成常用的模板代码,从而减少手动编写样板代码的需要。
Lombok 的特点:
-
减少模板代码:Lombok 可以通过注解自动生成常用的方法,如 getter/setter、构造函数、
toString、equals和hashCode方法,从而减少了编写样板代码的需要。 -
编译时处理:Lombok 使用注解处理器在编译时生成代码,这意味着生成的代码是实际的 Java 字节码,而不是运行时代理或字节码操纵。
-
非侵入性:Lombok 注解不会对现有的代码库造成侵入性影响,你可以在任何现有的 Java 项目中引入 Lombok。
1.2 Lombok 的引入
Maven:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>x.x.x</version>
<scope>provided</scope>
</dependency>
Gradle:
compileOnly 'org.projectlombok:lombok:x.x.x'
annotationProcessor 'org.projectlombok:lombok:x.x.x'
注意:
- 在 IDEA 中使用,需要安装 Lombok 插件。
- 在 Spring Boot 2.1.x 后,已经在
spring-boot-dependencies中内置,引入时无需指定版本。
1.3 Lombok 的原理
在 IDEA 中,如果不安装 Lombok 插件,使用 Lombok,在编译期是无法通过的。而安装 Lombok 插件后,查看 .class 文件,会发现增强的代码已经存在了,而 .java 文件中是无法看到的。
Lombok 通过利用 Java 编译器的注解处理 API 在编译时生成额外的代码,从而达到减少模板代码的目的。当编译器遇到带有 Lombok 注解的代码时,Lombok 会介入编译过程,读取注解,并为标注的代码生成相应的实现。这个过程对开发者是透明的,开发者只需要在代码中使用 Lombok 提供的注解,然后编译器在编译 Java 文件时会处理这些注解。
2、基础注解
2.1 Setter
- 作用:为类的私有字段生成对应的
setter()方法。 - 位置:类级别、字段级别。
- 示例:
// 1. 使用后 Lombok
@Setter
public class Student {
private String name;
}
// 2. 不使用 Lombok
public class Student {
private String name;
public void setName(String name) {
this.name = name;
}
}
2.2 Getter
- 作用:为类的私有字段生成对应的
getter()方法。 - 位置:类级别、字段级别。
- 示例:
// 1. 使用后 Lombok
@Getter
public class Student {
private String name;
}
// 2. 不使用 Lombok
public class Student {
private String name;
public String getName() {
return this.name;
}
}
2.3 ToString
- 作用:为类生成
toString()方法,包含所有字段。 - 位置:类级别。
- 示例:
// 1. 使用后 Lombok
@ToString
public class Student {
private String name;
}
// 2. 不使用 Lombok
public class Student {
private String name;
@Override
public String toString() {
return ...;
}
}
2.4 NoArgsConstructor
- 作用:为类生成无参构造函数。
- 位置:类级别。
- 示例:
// 1. 使用后 Lombok
@NoArgsConstructor
public class Student {
private String name;
}
// 2. 不使用 Lombok
public class Student {
private String name;
public Student() {
this.name = "";
}
}
2.5 AllArgsConstructor
- 作用:为类生成包含所有字段的构造函数。
- 位置:类级别。
- 示例:
// 1. 使用后 Lombok
@AllArgsConstructor
public class Student {
private String name;
}
// 2. 不使用 Lombok
public class Student {
private String name;
public Student(String name) {
this.name = name;
}
}
2.6 RequiredArgsConstructor
- 作用:为类生成包含所有
final字段的构造函数。 - 位置:类级别。
- 示例:
// 1. 使用后 Lombok
@AllArgsConstructor
public class Student {
private final String name;
private int age;
}
// 2. 不使用 Lombok
public class Student {
private final String name;
private int age;
public Student(String name) {
this.name = name;
}
}
2.7 EqualsAndHashCode
- 作用:为类生成
equals()和hashCode()方法。 - 位置:类级别。
- 示例:
// 1. 使用后 Lombok
@EqualsAndHashCode
public class Student {
private final String name;
private int age;
}
// 2. 不使用 Lombok
public class Student {
private final String name;
private int age;
public boolean equals(Student student) {
// ...
}
public
}
2.8 Data
- 作用:是一个复合注解,相当于 @ToString + @EqualsAndHashCode + @Getter + @Setter
- 位置:类级别。
- 示例:
// 1. 使用后 Lombok
@Data
public class Student {
private String name;
private int age;
}
// 2. 不使用 Lombok
public class Student {
private String name;
private int age;
public Student() {
this.name = "";
this.age = 0;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
// ...
}
@Override
public int hashCode() {
// ...
}
}
2.9 Value
- 作用:用于生成不可变对象,所有字段默认为 final,。它是一个复合注解,相当于 @ToString + @EqualsAndHashCode + @Getter + @RequiredArgsConstructor。
- 位置:类级别。
- 示例:
// 1. 使用后 Lombok
@Value
public class Student {
private final String name;
private final int age;
}
// 2. 不使用 Lombok
public class Student {
private final String name;
private final int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
@Override
public boolean equals(Object o) {
// ...
}
@Override
public int hashCode() {
// ...
}
@Override
public String toString() {
// ...
}
}
2.10 Builder
- 作用:为类生成建造者模式的代码,方便复杂对象的构建。
- 位置:类级别。
- 示例:
// 1. 使用后 Lombok
@Builder
public class Student {
private String name;
private int age;
}
// 2. 不使用 Lombok
public class Student {
private String name;
private int age;
// 私有构造函数
private Student() {}
public static class Builder {
private String name;
private int age;
public StudentBuilder name(String name) {
this.name = name;
return this;
}
public StudentBuilder age(int age) {
this.age = age;
return this;
}
public Student build() {
Student student = new Student();
student.name = this.name;
student.age = this.age;
return student;
}
}
}
3、其他注解
3.1 Slf4j
- 作用:为类生成一个日志对象,支持 SLF4J 日志框架。
- 位置:类级别。
- 示例:
// 1. 使用后 Lombok
@Slf4j
public class Student {
private String name;
private int age;
}
// 2. 不使用 Lombok
public class Student {
// 创建一个 Logger 实例
private static final Logger log = LoggerFactory.getLogger(MyClass.class);
private String name;
private int age;
}
3.2 SneakyThrows
- 作用:允许方法抛出一个或多个检查异常,而不需要在方法签名中声明。
- 位置:方法级别。
- 示例:
// 1. 使用后 Lombok
public class Student {
private String name;
private int age;
@SneakyThrows
public String getName() {
// 抛出 Exception
return name;
}
@SneakyThrows
public int getAge() {
// 抛出 Exception
return age;
}
}
// 2. 不使用 Lombok
public class Student {
private String name;
private int age;
public String getName() {
try {
// 抛出 Exception
return name;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public int getAge() {
try {
// 抛出 Exception
return age;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
3.3 Synchronized
- 作用:为方法生成同步代码块,确保线程安全。
- 位置:方法级别。
- 示例:
// 1. 使用后 Lombok
public class Counter {
private int count = 0;
@Synchronized
public void increment() {
count++;
}
@Synchronized
public int getCount() {
return count;
}
}
// 2. 不使用 Lombok
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
3.4 UtilityClass
- 作用:标记工具类,防止实例化和继承。
- 位置:类级别。
- 示例:
@UtilityClass
public class StringUtils {
/** * 将字符串转换为大写,如果字符串为 null,则返回 null。 */
public static String toUpperCase(String str) {
return str == null ? null : str.toUpperCase();
}
/** * 检查字符串是否为 null 或空。 */
public static boolean isNullOrEmpty(String str) {
return str == null || str.trim().isEmpty();
}
}
3.5 NotNull
- 作用:确保方法参数不为 null,如果为 null 则抛出 NullPointerException 异常。
- 位置:方法参数级别。
- 示例:
public void registerUser(@NonNull String username) {
// ...
}
3.6 Nullable
- 作用:标记字段、方法参数或返回值可以为 null。
- 位置:字段级别、方法参数级别、返回值级别。
- 示例:
public class UserService {
@Nullable
private String optionalField;
public @Nullable String findUserById(int id) {
// ...
return null;
}
public void processUser(@Nullable String username) {
// ...
}
}
3.7 Cleanup
- 作用:自动释放资源,类似于 Java 7 引入的 try-with-resources 语句。当标记的资源不再需要时,Lombok 会自动调用其
close方法。 - 位置:字段级别、方法参数级别、返回值级别。
- 示例:
@Cleanup Reader reader = new StringReader("xxx");
int data = reader.read();
while (data != -1) {
// ...
}