Lombok常用注解及功能详解

发布于:2025-08-02 ⋅ 阅读:(14) ⋅ 点赞:(0)

Java开发中,实体类的getter/setter、构造方法、toString()等模板代码往往占据大量篇幅,不仅编写繁琐,还会降低代码可读性,Lombok通过注解机制自动生成这些模板代码,让我们能够更专注于核心业务逻辑。

一、Lombok简介与环境配置

1.1 什么是Lombok?

Lombok是一个Java库,通过注解处理器在编译期自动生成模板代码(如gettersetter),无需手动编写。它的核心优势是:

  • 减少模板代码,精简类定义;
  • 避免修改字段后忘记更新getter/setter的问题;
  • 提高代码可读性,聚焦业务逻辑。

1.2 环境配置

1.2.1 Maven项目

pom.xml中添加依赖:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
    <optional>true</optional> <!-- 避免传递依赖 -->
</dependency>
1.2.2 Gradle项目

build.gradle中添加:

implementation 'org.projectlombok:lombok:1.18.24'
annotationProcessor 'org.projectlombok:lombok:1.18.24'
1.2.3 IDE配置(关键)

Lombok通过编译期生成代码,IDE需安装插件才能识别生成的方法(否则会报“方法不存在”错误):

  • IntelliJ IDEA
    1. 打开File → Settings → Plugins
    2. 搜索“Lombok”并安装,重启IDE;
    3. 开启注解处理:Settings → Build, Execution, Deployment → Compiler → Annotation Processors → 勾选Enable annotation processing
  • Eclipse
    1. 安装Lombok插件(官网下载lombok.jar,双击运行并指定Eclipse安装目录);
    2. 重启Eclipse。

二、Lombok常用注解详解

2.1 @Data:一站式生成核心方法

功能:自动生成gettersettertoString()equals()hashCode()方法,以及包含所有字段的构造方法。

使用示例

import lombok.Data;

@Data
public class User {
    private Long id;
    private String username;
    private Integer age;
}

等价于手动编写

public class User {
    private Long id;
    private String username;
    private Integer age;

    // getter
    public Long getId() { return id; }
    public String getUsername() { return username; }
    public Integer getAge() { return age; }

    // setter
    public void setId(Long id) { this.id = id; }
    public void setUsername(String username) { this.username = username; }
    public void setAge(Integer age) { this.age = age; }

    // toString
    public String toString() { 
        return "User(id=" + id + ", username=" + username + ", age=" + age + ")"; 
    }

    // equals和hashCode(基于所有字段)
    public boolean equals(Object o) { /* 实现 */ }
    public int hashCode() { /* 实现 */ }

    // 全参构造方法
    public User(Long id, String username, Integer age) {
        this.id = id;
        this.username = username;
        this.age = age;
    }
}

注意

  • @Data不包含无参构造方法,若需要需额外添加@NoArgsConstructor
  • 适合POJO类(如实体类、DTO),不建议在复杂业务类中使用。

2.2 @Getter/@Setter:单独生成getter/setter

功能:为类中所有字段(或指定字段)生成getter/setter方法。

使用示例

import lombok.Getter;
import lombok.Setter;

@Getter // 为所有字段生成getter
@Setter // 为所有字段生成setter
public class Product {
    private Long id;
    private String name;
    
    @Getter(AccessLevel.PRIVATE) // 仅为price生成private getter
    @Setter(AccessLevel.PROTECTED) // 仅为price生成protected setter
    private Double price;
}

关键参数

  • AccessLevel:指定方法访问权限(PUBLICPROTECTEDPACKAGEPRIVATE),默认PUBLIC

适用场景

  • 只需生成部分字段的getter/setter
  • 需要控制getter/setter的访问权限。

2.3 @ToString:生成toString()方法

功能:生成包含类名和字段的toString()方法,可指定包含/排除字段。

使用示例

import lombok.ToString;

@ToString(
    includeFieldNames = true, // 输出字段名(默认true)
    exclude = "password", // 排除password字段
    of = {"username", "age"} // 仅包含指定字段(与exclude二选一)
)
public class User {
    private Long id;
    private String username;
    private Integer age;
    private String password;
}

生成的toString()

public String toString() {
    return "User(username=" + username + ", age=" + age + ")";
}

注意

  • excludeof不可同时使用;
  • 若继承父类,可添加callSuper = true包含父类的toString()结果(默认false)。

2.4 @NoArgsConstructor/@AllArgsConstructor:生成构造方法

  • @NoArgsConstructor:生成无参构造方法;
  • @AllArgsConstructor:生成包含所有字段的构造方法。

使用示例

import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
public class Book {
    private String isbn;
    private String title;
    private String author;
}

生成的构造方法

// 无参构造
public Book() {}

// 全参构造
public Book(String isbn, String title, String author) {
    this.isbn = isbn;
    this.title = title;
    this.author = author;
}

注意

  • 若类中已有构造方法,@NoArgsConstructor会覆盖默认无参构造(若未显式定义);
  • 配合@Data使用时,需显式添加@NoArgsConstructor(因@Data不包含无参构造)。

2.5 @RequiredArgsConstructor:生成必需字段的构造方法

功能:为final或被@NonNull标注的字段生成构造方法。

使用示例

import lombok.RequiredArgsConstructor;
import lombok.NonNull;

@RequiredArgsConstructor
public class Order {
    private final Long orderId; // final字段(必需)
    @NonNull private String productName; // @NonNull标注(必需)
    private Integer quantity; // 普通字段(非必需)
}

生成的构造方法

public Order(Long orderId, String productName) {
    this.orderId = orderId;
    if (productName == null) {
        throw new NullPointerException("productName is marked non-null but is null");
    }
    this.productName = productName;
}

适用场景

  • 依赖注入(如构造方法注入@Autowired);
  • 确保核心字段必须初始化。

2.6 @NonNull:字段非空校验

功能:在构造方法或setter中为字段添加非空校验,若为null则抛出NullPointerException

使用示例

import lombok.NonNull;
import lombok.Setter;

public class User {
    private Long id;
    @NonNull private String username; // 非空校验

    @Setter
    @NonNull private Integer age; // setter中添加非空校验
}

生成的代码

public class User {
    private Long id;
    private String username;
    private Integer age;

    public User(String username) {
        if (username == null) {
            throw new NullPointerException("username is marked non-null but is null");
        }
        this.username = username;
    }

    public void setAge(Integer age) {
        if (age == null) {
            throw new NullPointerException("age is marked non-null but is null");
        }
        this.age = age;
    }
}

注意@NonNull需配合构造方法或setter使用(如与@Data@Setter等注解一起用)。

2.7 @Slf4j:简化日志对象创建

功能:自动生成日志对象(private static final Logger log = LoggerFactory.getLogger(类名.class);),支持主流日志框架(Logback、Log4j2等)。

使用示例

import lombok.extern.slf4j.Slf4j;

@Slf4j // 生成log对象
public class OrderService {
    public void createOrder() {
        log.info("开始创建订单"); // 直接使用log对象
        try {
            // 业务逻辑
            log.debug("订单创建成功");
        } catch (Exception e) {
            log.error("订单创建失败", e); // 打印异常
        }
    }
}

等价于手动编写

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OrderService {
    private static final Logger log = LoggerFactory.getLogger(OrderService.class);

    public void createOrder() {
        log.info("开始创建订单");
        // ...
    }
}

类似注解

  • @Log:对应java.util.logging.Logger
  • @Log4j:对应Log4j 1.x;
  • @Log4j2:对应Log4j 2.x。
  • 推荐使用@Slf4j(Slf4j是日志门面,可适配不同日志框架)。

2.8 @Builder:实现建造者模式

功能:为类生成建造者模式代码,支持链式调用创建对象。

使用示例

import lombok.Builder;
import lombok.ToString;

@Builder
@ToString
public class User {
    private Long id;
    private String username;
    private Integer age;
}

使用建造者创建对象

public class Test {
    public static void main(String[] args) {
        // 链式调用设置属性
        User user = User.builder()
                       .id(1L)
                       .username("张三")
                       .age(20)
                       .build(); // 构建对象
        System.out.println(user); // 输出:User(id=1, username=张三, age=20)
    }
}

优势

  • 相比构造方法,无需记忆参数顺序;
  • 支持选择性设置字段(无需为可选字段创建多个构造方法)。

注意@Builder默认生成全参私有构造方法,若需公开构造方法,需配合@NoArgsConstructor@AllArgsConstructor

2.9 @Value:生成不可变类

功能:生成不可变类(类似@Data,但字段默认为final,且无setter)。

使用示例

import lombok.Value;

@Value
public class ImmutableUser {
    Long id;
    String username;
    Integer age;
}

生成的代码特点

  • 所有字段被final修饰(不可修改);
  • 生成getter,但无setter
  • 生成全参构造方法(必须初始化所有字段);
  • 生成toString()equals()hashCode()

适用场景

  • 存储常量数据(如配置信息);
  • 线程安全的不可变对象。

2.10 @SneakyThrows:简化异常处理

功能:自动捕获受检异常(Checked Exception)并包装为运行时异常抛出,无需显式try-catchthrows声明。

使用示例

import lombok.SneakyThrows;
import java.io.FileInputStream;

public class FileUtil {
    // 无需声明throws IOException
    @SneakyThrows
    public static void readFile() {
        FileInputStream fis = new FileInputStream("test.txt");
        // ...
    }
}

生成的代码

public class FileUtil {
    public static void readFile() {
        try {
            FileInputStream fis = new FileInputStream("test.txt");
        } catch (IOException e) {
            throw new RuntimeException(e); // 包装为运行时异常
        }
    }
}

注意

  • 谨慎使用,可能隐藏异常类型(调用者无法通过throws声明感知受检异常);
  • 适合简化工具类中的异常处理。

三、Lombok注解组合使用场景

3.1 实体类(POJO)

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.ToString;

@Data // getter、setter、toString等
@NoArgsConstructor // 无参构造(JSON反序列化需要)
@AllArgsConstructor // 全参构造(测试用)
@ToString(exclude = "password") //  toString排除密码
public class User {
    private Long id;
    private String username;
    @NonNull // 非空校验
    private String password;
    private Integer age;
}

3.2 服务类(Service)

import lombok.extern.slf4j.Slf4j;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@Slf4j // 日志
@RequiredArgsConstructor // 构造方法注入依赖
public class UserService {
    private final UserMapper userMapper; // final字段(构造方法注入)

    public User getUserById(Long id) {
        log.info("查询用户ID:{}", id);
        return userMapper.selectById(id);
    }
}

3.3 不可变DTO

import lombok.Value;
import lombok.Builder;

@Value // 不可变类
@Builder // 支持建造者模式创建
public class UserDTO {
    Long id;
    String username;
    Integer age;
}

四、Lombok的优缺点与避坑指南

4.1 优点

  1. 减少模板代码:省去大量gettersetter等重复代码;
  2. 提高开发效率:新增字段时无需手动更新相关方法;
  3. 代码更简洁:聚焦核心业务逻辑,可读性提升。

4.2 缺点

  1. 强依赖插件:IDE必须安装Lombok插件,否则会报错;
  2. 调试困难:生成的代码在源码中不可见,调试时需查看编译后的class文件;
  3. 过度使用风险:滥用@Data可能导致类职责不清晰;
  4. 兼容性问题:某些框架(如序列化工具)可能无法识别生成的方法。

4.3 避坑指南

  1. 避免在父类使用@Data:子类继承后可能导致equals()hashCode()逻辑错误;
  2. 谨慎使用@SneakyThrows:不要在业务核心逻辑中隐藏受检异常,以免影响异常处理;
  3. 序列化注意:若类需要序列化(如实现Serializable),建议手动编写serialVersionUID(Lombok不自动生成);
  4. 版本兼容:确保Lombok版本与JDK版本兼容(如JDK 17需Lombok 1.18.20+);
  5. 代码审查:生成的代码虽不可见,但需在审查时考虑其逻辑(如equals()是否符合预期)。

总结

核心推荐注解:

  • 实体类:@Data + @NoArgsConstructor + @AllArgsConstructor
  • 服务类:@Slf4j + @RequiredArgsConstructor
  • 不可变对象:@Value
  • 日志:@Slf4j

若这篇内容帮到你,动动手指支持下!关注不迷路,干货持续输出!
ヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノ


网站公告

今日签到

点亮在社区的每一天
去签到