Lombok 是一个 Java 库,通过注解处理器在编译时自动生成常用的代码,如 getter/setter 方法、构造函数、toString 方法、equals 和 hashCode 方法等。这样开发者无需手动编写这些重复性的模板代码,从而专注于业务逻辑的实现
Lombok 利用 Java 的注解处理器(Annotation Processor)在编译阶段修改抽象语法树(AST),添加必要的代码。这些代码在编译后的字节码中存在,但在源代码中隐藏,从而保持代码的简洁性。
常用注解
@Getter 和 @Setter
自动为类的字段生成 getter 和 setter 方法
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class User {
private String name;
private int age;
}
编译后生成代码
public class User {
private String name;
private int age;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
@ToString
生成 toString
方法,默认包括所有字段
import lombok.ToString;
import lombok.Getter;
@ToString
@Getter
public class User {
private String name;
private int age;
}
编译后的代码
public class User {
private String name;
private int age;
public String getName() { return this.name; }
public int getAge() { return this.age; }
@Override
public String toString() {
return "User(name=" + this.getName() + ", age=" + this.getAge() + ")";
}
}
@EqualsAndHashCode
自动生成 equals 和 hashCode 方法,用于比较对象
import lombok.EqualsAndHashCode;
import lombok.Getter;
@EqualsAndHashCode
@Getter
public class User {
private String name;
private int age;
}
编译后的代码
public class User {
private String name;
private int age;
public String getName() { return this.name; }
public int getAge() { return this.age; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return this.getAge() == user.getAge() &&
java.util.Objects.equals(this.getName(), user.getName());
}
@Override
public int hashCode() {
return java.util.Objects.hash(this.getName(), this.getAge());
}
}
@NoArgsConstructor、@AllArgsConstructor 和 @RequiredArgsConstructor
自动生成不同类型的构造函数
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.Getter;
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Getter
public class User {
private String name;
private final int age;
}
编译后的代码
public class User {
private String name;
private final int age;
// 无参构造函数
public User() {
}
// 全参构造函数
public User(String name, int age) {
this.name = name;
this.age = age;
}
// 必填字段的构造函数(final 或 @NonNull)
public User(int age) {
this.age = age;
}
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public int getAge() { return this.age; }
}
@Data
综合应用多个注解,生成 getter/setter、toString
、equals
、hashCode
和所有字段的构造函数。
import lombok.Data;
@Data
public class User {
private String name;
private int age;
}
编译后的代码
public class User {
private String name;
private int age;
// Getter 和 Setter
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public int getAge() { return this.age; }
public void setAge(int age) { this.age = age; }
// toString 方法
@Override
public String toString() {
return "User(name=" + this.getName() + ", age=" + this.getAge() + ")";
}
// equals 和 hashCode 方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return this.getAge() == user.getAge() &&
java.util.Objects.equals(this.getName(), user.getName());
}
@Override
public int hashCode() {
return java.util.Objects.hash(this.getName(), this.getAge());
}
}
@Builder
提供建造者模式(Builder Pattern),便于创建复杂对象
import lombok.Builder;
@Builder
public class User {
private String name;
private int age;
private String email;
}
编译后的代码
public class User {
private String name;
private int age;
private String email;
private User(UserBuilder builder) {
this.name = builder.name;
this.age = builder.age;
this.email = builder.email;
}
public static UserBuilder builder() {
return new UserBuilder();
}
// Builder 类
public static class UserBuilder {
private String name;
private int age;
private String email;
UserBuilder() {
}
public UserBuilder name(String name) {
this.name = name;
return this;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public UserBuilder email(String email) {
this.email = email;
return this;
}
public User build() {
return new User(this);
}
public String toString() {
return "User.UserBuilder(name=" + this.name + ", age=" + this.age + ", email=" + this.email + ")";
}
}
// Getter 和 Setter
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public int getAge() { return this.age; }
public void setAge(int age) { this.age = age; }
public String getEmail() { return this.email; }
public void setEmail(String email) { this.email = email; }
}
使用方式
public class Main {
public static void main(String[] args) {
User user = User.builder()
.name("Alice")
.age(30)
.email("alice@example.com")
.build();
System.out.println(user);
}
}
输出
User(name=Alice, age=30, email=alice@example.com)
@Slf4j
自动为类生成一个 org.slf4j.Logger
日志对象
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class UserService {
public void createUser() {
log.info("Creating a new user...");
// 业务逻辑
}
}
编译后的代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserService {
private static final Logger log = LoggerFactory.getLogger(UserService.class);
public void createUser() {
log.info("Creating a new user...");
// 业务逻辑
}
}
使用 Lombok
添加 maven 依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
在 IntelliJ 2020.3 版本后 lombok plugin 已经被内置,无需额外安装
在许多 Java 项目中,尤其是使用 ORM 的项目,实体类通常包含大量的 getter、setter、构造函数,Lombok 可以显著简化实体类、DTO 的编写
不要滥用 lombok
尽管 Lombok 提供了显著的优势,如减少样板代码和提高开发效率,但在实践中,有些代码规约和开发团队选择不推荐或限制 Lombok 的使用
- 代码隐藏:自动生成的方法(如 getters、setters、构造函数等)在源代码中不可见,可能导致开发者对类的实际行为产生误解。
- 调试复杂性:调试时,IDE 可能无法直接显示 Lombok 生成的代码,增加了追踪问题的难度。
- 文档不全:由于 Lombok 生成的代码在源代码中不可见,自动文档工具可能遗漏重要的方法和类信息。
- 自动化工具依赖:某些工具可能依赖于具体的代码实现,如果 Lombok 生成的代码不符合预期,可能会导致工具失败或生成错误的输出。
Java 14 引入的 Records 提供了一种简洁的方式来定义不可变的数据类,无需手动编写 getter、equals、hashCode 和 toString 方法,如果数据类主要用于存储不可变的属性,Records 是一个理想的选择
定义类
public record User(Long id, String name, String email) {}
使用
public class Main {
public static void main(String[] args) {
User user = new User(1L, "Alice", "alice@example.com");
System.out.println(user);
// 访问 Record 的字段
System.out.println("Name: " + user.name());
System.out.println("Email: " + user.email());
}
}
输出
User[id=1, name=Alice, email=alice@example.com]
Name: Alice
Email: alice@example.com