遇到的问题

在写代码时,有时因为需要定义一些重复的参数,为了复用之前传参的DTO,会对原有的类进行继承,从而达到避免重复代码的效果。

但是,当父类中使用了lombok的@Builder注解,子类也需要@builder注解时,就会出现异常

排查和解决

由于实际的代码存在敏感信息,这里分别定义两个类Parent和Child来进行场景的模拟

@Data
@Builder
class Parent {
    private String parentProperty1;

    private String parentProperty2;
}

@EqualsAndHashCode(callSuper = true)
@Data
@Builder
class Child extends Parent {
    private String childProperty1;
}

这时在尝试使用子类的builder方法时,发现没有办法链式调用,使用时只能初始化子类中的变量,编译时会直接失败,抛出异常

Error:(160, 1) java: 无法将类 org.example.Parent中的构造器 Parent应用到给定类型;
  需要: java.lang.String,java.lang.String
  找到: 没有参数
  原因: 实际参数列表和形式参数列表长度不同

这是在编译子类的@Builder注解时出现的异常,原因直观的看起来是找不到构造器,在Parent类上加上@NoArgsConstructor和@AllArgsConstructor这两个注解就能解决这个问题,但是同时会出现新的编译问题,是什么问题先按下不表。

想要简单的解决加上@Builder之后就会报错的问题,那么直接把父类的@Builder这个注解拿掉就行了,不过这时无法设置父类的属性,如果还想在子类中使用构建器模式来初始化父类的属性,还有另一种方法,在子类中实现一个能够初始化父类属性的构造器,并在这个构造方法上添加@Builder注解。

这时的代码:

@Data
@NoArgsConstructor
@AllArgsConstructor
class Parent {
    private String parentProperty1;

    private String parentProperty2;
}


@Data
class Child extends Parent {
    private String childProperty1;

    @Builder
    public Child(String parentProperty1, String parentProperty2, String childProperty1){
        super(parentProperty1, parentProperty2);
        this.childProperty1 = childProperty1;
    }
}

不过使用这种方法只能解决子类使用@Builder的问题,但是在更多的时候,父类也是需要@Builder这个注解的,那么在这种情况下应该怎么解决呢?

而且这时还会有另一个新的问题出现,使用了@Data注解和@Builder注解的子类无法使用无参构造器来创建对象,这时需要在子类上显式的加上@NoArgsConstructor这个注解才能解决。

如果要更细致的分析,就得从从@Builder的原理说起,了解@Builder到底生成了哪些代码?

这一步可以自己编译代码看看,当然如果自己写过builder建造者模式的实现,应该能想到他是实现了一个名称以Builder为后缀的静态内部类,在调用build()方法的时候调用外部类的全参构造方法来生成外部类的实例。

回到之前的问题,当子类和父类同时存在@Builder注解时,在解决了构造器异常之后,如果编译代码,会出现异常:

Error:(164, 5) java: org.example.Child中的builder()无法覆盖org.example.Parent中的builder()
  返回类型org.example.Child.ChildBuilder与org.example.Parent.ParentBuilder不兼容

这里的问题就简单一些了,父类的builder()方法返回的是ParentBuilder这个静态内部类类型的对象,而子类生成的builder()方法返回的是ChildBuilder这个类型的对象。

两者的名称重复了,而由于返回类型不兼容而无法按覆盖。

根据@Builder注解的源码可以发现名称是可以自定义的,于是可以通过给子类builder方法自定义名称的方式来解决这个问题。

最终的代码:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
class Parent {
    private String parentProperty1;

    private String parentProperty2;
}


@Data
class Child extends Parent {
    private String childProperty1;

    @Builder(builderMethodName = "childBuilder")
    public Child(String parentProperty1, String parentProperty2, String childProperty1){
        super(parentProperty1, parentProperty2);
        this.childProperty1 = childProperty1;
    }
}

结尾

值得一提的是,1.8.2之后版本的lombok提供了一个新的注解@SuperBuilder来解决这个问题,不过我没有用过,而且从网上搜索出来的结果来看,还是存在一些问题的,建议谨慎升级。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持Devmax。

解决lombok 父类和子类builder不兼容的问题的更多相关文章

  1. python重用父类功能的两种方式实例详解

    这篇文章主要介绍了python重用父类功能的两种方式,方式一是跟继承没有关系的,而方式二的super()是依赖于继承的,并且即使没有直接继承关系,super()仍然会按照MRO继续往后查找,本文给大家介绍的非常详细,需要的朋友可以参考下

  2. PHP设计模式之建造者模式(Builder)原理与用法案例详解

    这篇文章主要介绍了PHP设计模式之建造者模式(Builder)原理与用法,结合具体实例形式详细Fenix了建造者模式的概念、原理、用法及操作注意事项,需要的朋友可以参考下

  3. Lombok注解-@SneakyThrows的使用

    这篇文章主要介绍了Lombok注解-@SneakyThrows的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  4. springboot使用小工具之Lombok、devtools、Spring Initailizr详解

    这篇文章主要介绍了springboot使用小工具之Lombok、devtools、Spring Initailizr详解,Lombok可以代替手写get、set、构造方法等,需要idea装插件lombok,本文通过示例代码给大家介绍的非常详细,需要的朋友可以参考下

  5. MyBatisPlus+Lombok实现分页功能的方法详解

    Lombok是一个Java类库,提供了一组注解,简化POJO实体类开发。本文将为大家介绍一下Lombok的使用以及如何利用MyBatisPlus+Lombok实现分页功能,感兴趣的可以动手尝试一下

  6. 减少代码开发工作的Java库lombok及注解的使用学习

    不久前发现有一个java第三方库可以在一定程度上帮助我们从体力劳动中解救出来,它就是lombok。它提供了一些简单的注解,并以此来消除java中臃肿的模版代码。本文对于一些常用到的注解做了一个简要的记录,希望有更多的人enjoy it

  7. vite + electron-builder 打包配置详解

    这篇文章主要为大家介绍了electron基于vite + electron-builder 打包配置详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  8. Lombok使用@Tolerate实现冲突兼容问题

    这篇文章主要介绍了Lombok使用@Tolerate实现冲突兼容问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  9. Spring Boot教程之提高开发效率必备工具lombok

    这篇文章主要介绍了Spring Boot教程之提高开发效率必备工具lombok的相关资料,需要的朋友可以参考下

  10. 解决lombok 父类和子类builder不兼容的问题

    这篇文章主要介绍了解决lombok 父类和子类builder不兼容的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部