在使用 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
是更加现代和优雅的方式,能让你的构造代码保持清晰和强大。