Java | Lombok @Builder排障指南:为什么 build 时默认值丢失?

关注:CodingTechWork

引言

在 Java 项目中,使用 Lombok 的 @Builder 注解可以让我们用链式调用快速创建对象。通常我们会为一些字段在类中直接设置默认值:

public class User {
    private String name = "defaultName";
    private int age = 18;
}

直接用 new User() 创建对象时,这些字段就会有默认值。但当我们使用 @Builder 构建对象时,发现这些默认值“消失”了:

@Builder
public class User {
    private String name = "defaultName";
    private int age = 18;
}

public class Main {
    public static void main(String[] args) {
        User user = User.builder().build();
        System.out.println(user.getName()); // 输出 null
        System.out.println(user.getAge());  // 输出 0
    }
}

问题分析:@Builder 和默认值冲突的原因

Lombok 的 @Builder 注解会生成一个独立的 Builder 类。Builder 类中,每个字段都会有自己的存储变量,当你调用 build() 时,会用 Builder 内部存储的值来创建对象。

关键点

  1. Builder 内部的字段默认值是 Java 类型默认值,而不是类字段的默认值。
  2. 所以即使你在类中给字段写了 private String name = "defaultName";,Builder 也不会去读取这个默认值。
  3. 如果你在 build() 之前没有调用对应的 setter 方法,这个字段就会保持 Builder 内部的默认值(String 为 null,int 为 0)。

解决方案:使用 @Builder.Default

Lombok 提供了 @Builder.Default 注解,专门用来解决这个问题。它会告诉 Builder,在构建对象时如果没有显式设置值,使用字段的初始化值作为默认值。

修改后的示例:

@Builder
public class User {
    @Builder.Default
    private String name = "defaultName";

    @Builder.Default
    private int age = 18;
}

public class Main {
    public static void main(String[] args) {
        User user = User.builder().build();
        System.out.println(user.getName()); // 输出 defaultName
        System.out.println(user.getAge());  // 输出 18
    }
}

工作原理:

  1. @Builder.Default 会在 Builder 类中生成一个 默认值初始化逻辑
  2. 当 build() 被调用时,如果 Builder 中没有设置这个字段,则使用默认值初始化字段。
  3. 如果 Builder 已经通过链式调用设置了值,则使用用户设置的值。

常见错误与注意事项

  1. 忘记加 @Builder.Default
@Builder
private String name = "defaultName"; // ❌ 错误

这种写法不会生效,build 后仍然是 null。

  1. 与 @NonNull 冲突
@Builder
@NonNull
@Builder.Default
private String name = "defaultName"; // ❌ Lombok 会报错

@NonNull@Builder.Default 不要同时使用,因为默认值初始化逻辑可能与非空检查冲突。

  1. 不要在构造器里重复初始化

如果你同时有全参构造器或者 @AllArgsConstructor 初始化字段,Builder 默认值可能不会生效。建议依赖 @Builder.Default 的初始化逻辑。

总结

  • 在类中直接给字段赋值,new 时会生效。
  • 使用 @Builder 构建对象时,类字段的默认值不会生效。
  • 解决方案是为字段添加 @Builder.Default 注解。
  • 注意与 @NonNull 或自定义构造器的冲突。

通过 @Builder.Default,我们就能让 Builder 构建对象时也保留默认值,从而避免 build 出来的对象字段为 null 或 0 的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值