Lombok @Builder注解的两大陷阱分析及解决

 更新时间:2026年01月14日 16:08:25   作者:刘火锅  
Lombok的@Builder注解简化了建造者模式的代码编写,但存在两个陷阱:无参构造函数消失和字段默认值失效,通过显式声明构造器和使用@Builder.Default注解,可以解决这些问题

问题概述

Lombok 的 @Builder 注解极大地简化了“建造者模式”的代码编写,但其默认行为存在两个非常隐蔽的陷阱:

陷阱一:无参构造函数消失

现象:当一个类同时使用 @Data 和 @Builder 后,原本可用的无参构造函数 new Entity() 突然不可用,编译报错。

陷阱二:字段默认值(初始化)失效

现象:在字段声明时设置的默认值(如 String status = “open”;),通过 Builder 创建对象时,若未显式设置该字段,其值将为 null 而非预期的 “open”。

陷阱一:无参构造函数消失

复现步骤

编写一个同时使用 @Data 和 @Builder 的类。

@Data
@Builder
public class User {
    private String name;
    private Integer age;
}

尝试在其他地方使用无参构造

User user = new User(); // 编译错误:找不到符号 User()

原因分析

  • @Data 会生成一个 @RequiredArgsConstructor。如果类中没有 final 或@NonNull 的字段,这个构造器就是无参的。此时,单独使用 @Data 是完全可以无参构造的。
  • @Builder 注解需要基于一个全参构造函数来工作。当它发现你没有显式提供任何构造器时,它会主动生成一个私有的、包含所有字段的全参构造函数。
  • @Builder 的生成行为取代了 @Data 生成 @RequiredArgsConstructor 的逻辑。最终,编译后的类中只剩下 @Builder 生成的私有全参构造器,导致无参构造器确实“消失”了。

解决方案

显式声明所需的全部构造器,避免 Lombok 的默认行为产生冲突。

@Data
@Builder
@NoArgsConstructor // 显式指定:我需要无参构造
@AllArgsConstructor // 显式指定:我需要全参构造(让Builder直接使用这个现成的)
public class User {
    private String name;
    private Integer age;
}

陷阱二:字段默认值(初始化)失效

复现步骤

编写一个带有字段默认值的类并使用 Builder。

@Data
@Builder
public class Order {
    private Long id;
    private String status = "open"; // 期望的默认值
}

使用 Builder 创建对象,但不设置 status 字段。

Order order = Order.builder().id(1L).build();
System.out.println(order.getStatus()); // 输出:null (预期是 "open")

原因分析

  • 字段的默认值 = "open"是在类的构造函数内部执行的。
  • @Builder 的 build() 方法本质上是调用了类的全参构造函数,并将 Builder 对象内部的字段值作为参数传入。关键点在于:构造函数会无条件使用传入的参数。
  • 如果你没有调用 .status(…) 方法,Builder 对象内部的 status 字段值就是 null。在调用 build() 时,执行的是 new Order(id, status),这个 null 被传入了构造函数,完全覆盖了类定义中 = “open” 的初始化操作。

解决方案

使用 Lombok 提供的 @Builder.Default 注解。

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Order {
    private Long id;
    
    @Builder.Default // 使用此注解标记
    private String status = "open";
}

@Builder.Default 的原理:

  • 它会指示 Lombok 在生成的 Builder 类中,预先将这个字段初始化为指定的默认值。
  • 如果后续没有显式设置该字段,build() 方法就会使用这个预先存在的默认值,而不是 null。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java的Spring AOP详细讲解

    Java的Spring AOP详细讲解

    章主要为大家详细介绍了Java的Spring AOP,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • 基于Java实现回调监听工具类

    基于Java实现回调监听工具类

    这篇文章主要为大家详细介绍了如何基于Java实现一个回调监听工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-04-04
  • Request与Session的存值取值操作

    Request与Session的存值取值操作

    这篇文章主要介绍了Request与Session的存值取值操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • java针对于时间转换的DateUtils工具类

    java针对于时间转换的DateUtils工具类

    这篇文章主要为大家详细介绍了java针对于时间转换的DateUtils工具类,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12
  • Spring循环引用失败问题源码解析

    Spring循环引用失败问题源码解析

    这篇文章主要为大家介绍了Spring循环引用失败问题源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • springBoot启动时让方法自动执行的几种实现方式

    springBoot启动时让方法自动执行的几种实现方式

    这篇文章主要介绍了springBoot启动时让方法自动执行的几种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Java语言资源国际化步骤解析

    Java语言资源国际化步骤解析

    这篇文章主要介绍了Java语言资源国际化步骤解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • SpringBoot生产环境打包如何去除无用依赖

    SpringBoot生产环境打包如何去除无用依赖

    这篇文章主要介绍了SpringBoot生产环境打包如何去除无用依赖问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • springboot入门之profile设置方式

    springboot入门之profile设置方式

    这篇文章主要介绍了springboot入门 profile设置方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • 详解Java设计模式编程中的依赖倒置原则

    详解Java设计模式编程中的依赖倒置原则

    这篇文章主要介绍了详解Java设计模式中的依赖倒置原则,针对面对对象编程中的抽象的运用,需要的朋友可以参考下
    2016-02-02

最新评论