使用Lombok @SuperBuilder隐藏父类字段的技术方案问询
问题解决方案
现有类层级结构
抽象类Parent2(第一层)
abstract class Parent2 { private P2_Param1 p2_param1; private P2_Param2 p2_param2; protected Parent2(P1_Param1 p1_param1) { p2_param1 = p1_param1.something(); p2_param2 = p1_param1.somethingElse(); } }
抽象类Parent1(第二层)
abstract class Parent1 extends Parent2 { private P1_Param1 p1_param1; protected Parent1(P1_Param1 p1_param1) { super(p1_param1); this.p1_param1 = p1_param1; } }
子类Child(共上百个类似实现)
class Child extends Parent1 { private C_Param1 c_param1; private C_Param2 c_param2; private C_Param3 c_param3; private C_Param4 c_param4; // ... 更多字段 public Child(P1_Param1 p1_param1) { super(p1_param1); } }
需求说明
长期以来这些子类仅用作Schema定义,现在需要让子类字段存储具体值,要求:
- 尽量少改动子类
- 避免为每个子类编写包含所有自身字段+
p1_param1的构造方法 - 理想方案是通过Lombok注解或修改父类实现
原本计划用@SuperBuilder(toBuilder = true)实现如下实例化方式:
var child = new Child(p1_param1) .toBuilder() .c_param1(c_param1) .build();
但问题是子类构建器会暴露父类的字段(如p2_param2),需要禁用这种访问。
可行方案及实现步骤
方案可行性结论
这个方案完全可行,通过调整Lombok注解的配置和父类的注解设置,就能做到父类字段不被子类构建器暴露。
具体实现步骤
父类不使用
@SuperBuilder
父类Parent2和Parent1保留原有构造逻辑即可,不需要添加@SuperBuilder注解。这样父类的字段不会被纳入子类的构建器体系,从根源避免暴露。子类单独添加
@Builder(toBuilder = true)注解
仅在子类上添加该注解,Lombok会自动为子类生成仅包含自身字段的构建器,同时保留toBuilder()方法的能力。子类的改动极少,仅需添加一行注解,完全不需要修改构造方法或其他代码。修改后的子类示例:
import lombok.Builder; @Builder(toBuilder = true) class Child extends Parent1 { private C_Param1 c_param1; private C_Param2 c_param2; private C_Param3 c_param3; private C_Param4 c_param4; // ... 更多字段 public Child(P1_Param1 p1_param1) { super(p1_param1); } }特殊场景适配(若必须用
@SuperBuilder)
如果因业务限制必须在父类使用@SuperBuilder,可以通过以下方式隐藏父类字段:- 在父类的私有字段上添加
@Builder.Default,并确保字段仅在父类构造逻辑中初始化,不对外暴露setter方法 - 自定义父类的构建器实现,将父类字段的设置方法设为私有或包级访问,阻止子类构建器调用
- 在父类的私有字段上添加
效果验证
调整后,子类调用toBuilder()生成的构建器只会包含自身的字段(如c_param1、c_param2等),父类的p2_param1、p2_param2、p1_param1不会出现在构建器的公共方法中,完全符合需求。同时实例化方式和你原本计划的一致,不需要修改调用代码。
内容的提问来源于stack exchange,提问作者AndrewM
相关产品推荐
相关产品推荐

