Lombok 是一款非常实用的工具,通过注解能消除冗长的 Java 代码,工程中需要导入 lombok.jar,相应 IDE 的安装方式可参考 官网。项目中使用到的注解主要是 @Data 和 @Builder,前一个注解用在类上,相当于同时使用了 @ToString、@EqualsAndHashCode、@Getter、@Setter 和 @RequiredArgsConstrutor;后一个主要用在类、构造器、方法上,能非常方便的实现建造者模式、链式编程,相关文档可参考 这里。
@Builder 注解
在有继承(Inheritance)关系的实体类中使用 @Builder 时,遇到子类的 Builder 对象无法使用到父类的属性,以下方例子来说明
如果是使用 Parent p = new Parent(); p.setParentAge(123);... 方式赋值,那么以下内容可忽略!
1 |
|
在使用 Child.builder().parentAge(18).parentName("zhangsan") 时编译失败,查看 Child 对应的 class 文件如下
1 | public class Child extends Parent { |
并未发现有父类的属性存在。若是在父类中加 @Builder 注解而子类不加,则会报如下错误
1 | Error:(14, 8) java: 无法将类 com.leaface.Parent中的构造器 Paren t应用到给定类型; |
之后参考了有关文档,将代码改成
1 |
|
PS:父类中的 @NoArgsConstructor 是在使用了 @Data 注解后,为解决子类出现 Lombok needs a default constructor in the base class 这个错误而加的
这样配置后,子类就能设置父类的属性了,注意:此时父类是没有加 @Builder 的,而我们项目中又需要这个注解,若是都加上 @Builder,子类编译报错
1 | Error:(17, 5) java: com.leaface.Child 中的 builder() 无法隐藏 com.leaface.Parent 中的 builder() |
以下是 @Builder 注解源码
1 | ({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR}) |
其中的 builderMethodName 默认为 builder,子类试图公开和父类具有相同名称的构建器,所以报错。
解决方案:为父类和子类分别指定不同名称的构建器!!!
例如在子类中加 builderMethodName = "leafChildBuilder",修改后代码如下
1 |
|
查看子类的 class 文件,发现已生成其对应的构建器 leafChildBuilder() 和父类的属性
1 | public static Child.ChildBuilder leafChildBuilder() { |
这里没有改父类的构建器名称,所以还是默认的 builder(),两者已不存在冲突
1 | public static Parent.ParentBuilder builder() { |
使用时,子类直接调 leafChildBuilder() 即可,父类还是使用默认的 builder()
1 | Child child = Child.leafChildBuilder().parentAge(88).childAge(18).childName("zhangsan").build(); |
@SuperBuilder 注解(推荐)
Lombok v1.18.2 推出了 @SuperBuilder 注解,这样就不用再定义特殊的构建器了,比如这样
1 |
|
使用默认的 builder() 调用即可
1 | Child child = Child.builder().parentAge(88).childAge(18).childName("zhangsan").build(); |
以上两种方式,赋值后均能通过 @Data 提供的 get 方法取到值。
@SuperBuilder 和 @Builder 不能在同一继承体系中混用,否则会编译失败。多层级继承中这两者的使用方式同上!
至此,Lombok @Builder 继承问题解决!
附录
最后分别附上使用了 @Builder 和 @SuperBuilder 后的父类、子类 class 文件(省略了 @Data 注解)
@Builder class
Parent.class ======>>>
1 | public class Parent { |
Child.class ======>>>
1 | public class Child extends Parent { |
@SuperBuilder class
Parent.class ======>>>
1 | public class Parent { |
Child.class ======>>>
1 | public class Child extends Parent { |
参考资料
Lombok @Builder
Lombok @SuperBuilder
Project Lombok
Lombok @Builder with Inheritance

