在使用 Lombok 时,@Builder 提供了非常优雅的方式构建对象。但当涉及类继承结构时,很多开发者会发现一个问题:

子类使用 @Builder 时,无法设置父类中的字段。

本文将详解为什么会这样,并介绍几种解决方案,特别推荐使用 @SuperBuilder 来优雅支持继承下的对象构造。


问题重现:@Builder 无法处理父类字段

来看一个简单的例子:

@Getter
public class Parent {
    private String parentField;
}

@Builder
@Getter
public class Child extends Parent {
    private String childField;
}

尝试构造:

Child child = Child.builder()
    .parentField("parent") // 编译错误:找不到 parentField()
    .childField("child")
    .build();

结果发现:父类字段 parentField 无法通过 builder 设置。

原因是:@Builder 默认只处理当前类的字段,不会考虑继承的父类字段。


✅ 正确做法:使用 @SuperBuilder

为了解决继承中的 builder 问题,Lombok 提供了 @SuperBuilder 注解。它是 @Builder 的增强版本,专门用于支持类继承结构下的构造。

示例代码

父类:

import lombok.experimental.SuperBuilder;
import lombok.Getter;

@SuperBuilder
@Getter
public class Parent {
    private String parentField;
}

子类:

import lombok.experimental.SuperBuilder;
import lombok.Getter;
import lombok.ToString;

@SuperBuilder
@Getter
@ToString(callSuper = true)
public class Child extends Parent {
    private String childField;
}

构造示例:

Child child = Child.builder()
    .parentField("Hello Parent")
    .childField("Hello Child")
    .build();

System.out.println(child);

输出结果:

Child(parentField=Hello Parent, childField=Hello Child)

特点总结

  • @SuperBuilder 支持链式构造父类字段;
  • 父类和子类都需使用 @SuperBuilder
  • 可搭配 toBuilder = true 实现对象复制修改。

⚠️ 其他方案(了解即可)

手动传递构造器参数(不推荐)

如果你坚持使用 @Builder,可以手动在子类构造器中接收并传递父类字段:

@Builder
public class Child extends Parent {
    private String childField;

    public Child(String parentField, String childField) {
        super(parentField);
        this.childField = childField;
    }
}

这虽然可以实现目标,但会丢失 Lombok 的自动化构造优势,维护成本高,不推荐使用


✅ 最佳实践建议

需求推荐方案
普通类构造@Builder
父子类都需构造字段@SuperBuilder
搭配 Jackson/JPA手动构造器或谨慎使用 @SuperBuilder(需测试兼容性)
有复制/修改需求@SuperBuilder(toBuilder = true)

结语

Lombok 的 @Builder 在平铺结构中非常方便,但面对继承结构时存在局限。此时使用 @SuperBuilder 是更加现代和优雅的方式,能让你的构造代码保持清晰和强大。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注