探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)


Lombok 是 Java 中深受开发者欢迎的代码简化库,其中 @Builder 和 @SuperBuilder 是常用的注解,用于简化对象构建流程。但 @Builder 和 @SuperBuilder 的使用并非没有限制,稍有不慎就会出现一些意想不到的问题。本文就来深入探讨这两个注解的常见坑点和使用建议。

@Builder 和 @SuperBuilder 的区别

  • @Builder:Lombok 的经典注解,用于为类生成 Builder 模式。它可以让我们更方便地创建对象,尤其是字段较多时。
  • @SuperBuilder:Lombok 引入的增强版,支持子类和父类的 Builder 模式,特别适用于继承结构中构建对象的场景。

虽然 @SuperBuilder 是专为继承结构设计的,但在简单对象构建中也有一些有用特性。然而,这两个注解都有一些可能遇到的坑。


坑点一:@Builder 不能直接用于继承结构

问题@Builder 不支持继承结构,如果直接在父类和子类上分别使用 @Builder,会导致子类无法正常调用父类的字段,甚至在编译时直接报错。

解决方案:在继承结构中推荐使用 @SuperBuilder,它专门为继承而设计,并能更好地支持父类与子类字段的构建。

// 父类
@SuperBuilder
public class Parent {
    private String name;
}

// 子类
@SuperBuilder
public class Child extends Parent {
    private int age;
}

// 使用
Child child = Child.builder().name("Alice").age(10).build();

总结:在有继承关系的类上始终选择 @SuperBuilder 而不是 @Builder


坑点二:@SuperBuilder 不能与 @NoArgsConstructor 直接共存

问题:有时我们需要 @NoArgsConstructor 无参构造函数,但如果直接与 @SuperBuilder 一起使用,会遇到编译冲突,导致构造器生成失败。

解决方案:可以借助 @NoArgsConstructorforce 属性,强制生成无参构造函数:

@NoArgsConstructor(force = true)
@SuperBuilder
public class Example {
    private final String field;
}

这样 Lombok 会生成无参构造器,同时支持 @SuperBuilder


坑点三:@SuperBuilder 不支持构造器上的自定义逻辑

问题:如果希望在构建对象时进行额外的校验或初始化逻辑(例如计算某些属性),@SuperBuilder 默认生成的构造方法并不会支持这些自定义逻辑。

解决方案:需要在 @SuperBuilder 中使用 @Builder.Default 为字段提供默认值,或者手动添加私有构造器:

@SuperBuilder
public class Example {
    private final String field;

    @Builder.Default
    private final int calculatedField = calculate();

    private int calculate() {
        // 自定义逻辑
        return field.length();
    }
}

这样可以确保默认值被正确初始化。


坑点四:@Builder.Default 在 @Builder 和 @SuperBuilder 中的局限

问题@Builder.Default 是 Lombok 为 Builder 提供的默认值机制,但如果使用 @Builder.Default 来初始化某些字段,@Builder 会生成不必要的重复代码,这会导致不一致的行为。

解决方案:尽量避免在复杂逻辑中依赖 @Builder.Default,如果确实需要默认值,建议直接使用构造函数来初始化,以避免误用。


坑点五:字段类型为 Collection 时的深坑

问题:当使用 @Builder.Default 为集合类型(如 ListSet)字段设置默认值时,Lombok 会为每次构建对象时提供一个共享的集合,这会导致并发问题和数据污染。

解决方案:应避免在集合类型字段上使用 @Builder.Default,而是在构造函数中初始化集合,以确保每次构建新对象时都创建一个新的集合实例。

@SuperBuilder
public class Example {
    private final List<String> list;

    public Example() {
        this.list = new ArrayList<>();
    }
}

小结

  1. 有继承关系时,优先使用 @SuperBuilder。
  2. @SuperBuilder 和 @NoArgsConstructor 需要结合 force 属性使用。
  3. 避免在自定义逻辑初始化时依赖 @Builder。
  4. 集合类型字段尽量在构造函数中初始化,避免使用 @Builder.Default

通过这些小技巧,你可以有效避免 @Builder@SuperBuilder 的踩坑问题,让代码更简洁、安全。希望本文能帮助你更好地使用 Lombok 的这些特性,让代码构建更加轻松。

推荐阅读文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔道不误砍柴功

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值