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

 更新时间:2022年09月21日 10:09:21   作者:Armour__r  
这篇文章主要介绍了解决lombok 父类和子类builder不兼容的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

遇到的问题

在写代码时,有时因为需要定义一些重复的参数,为了复用之前传参的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来解决这个问题,不过我没有用过,而且从网上搜索出来的结果来看,还是存在一些问题的,建议谨慎升级。

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

相关文章

  • java日志打印的完全使用指南

    java日志打印的完全使用指南

    日志就是记录程序的运行轨迹,方便查找关键信息,也方便快速定位解决问题,下面这篇文章主要给大家介绍了关于java日志打印使用的相关资料,需要的朋友可以参考下
    2022-01-01
  • Java动态规划之硬币找零问题实现代码

    Java动态规划之硬币找零问题实现代码

    这篇文章主要介绍了Java动态规划之硬币找零问题实现代码,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • SpringBoot中基于JWT的单token授权和续期方案步骤详解

    SpringBoot中基于JWT的单token授权和续期方案步骤详解

    在前后端分离架构中,用户登录后,后端生成JWT Token返给前端存于LocalStorage,每次请求携带Token验证身份,后端校验其有效性,本文给大家介绍SpringBoot中基于JWT的单token授权和续期方案步骤详解,感兴趣的朋友一起看看吧
    2024-09-09
  • 教你怎么用Java开发扫雷游戏

    教你怎么用Java开发扫雷游戏

    我们那时候上机经常玩扫雷,试想如果我当年可以用 java 写个扫雷出来,那场面不用我多说了吧,大家让开,我要开始装逼了,之前用JavaScript写过了一个扫雷,这次我用java再写了一遍,权当是复习咯.文中有非常详细的代码示例,需要的朋友可以参考下
    2021-05-05
  • MyBatis-Plus中自动填充功能的用法示例详解

    MyBatis-Plus中自动填充功能的用法示例详解

    有些时候我们可能会有这样的需求,插入或者更新数据时,希望有些字段可以自动填充数据,比如密码、version、注册时默认的用户角色等,在MP中提供了这样的功能,可以实现自动填充功能,需要的朋友可以参考下
    2022-12-12
  • Java 数组高频考点分析讲解

    Java 数组高频考点分析讲解

    数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同。Java 语言中提供的数组是用来存储固定大小的同类型元素
    2022-04-04
  • SpringSecurity数据库进行认证和授权的使用

    SpringSecurity数据库进行认证和授权的使用

    本文主要介绍了用户的账号、密码以及角色信息在数据库中的认证和授权,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • SpringBoot异常错误页面实现方法介绍

    SpringBoot异常错误页面实现方法介绍

    在项目访问的时候我们经常会发生错误或者页面找不到,比如:资源找不到404,服务器500错误,默认情况下springboot的处理机制都是去跳转内部的错误地址:/error 和与之对应的一个错误页面
    2022-09-09
  • SpringBoot导入mail依赖报错问题解决

    SpringBoot导入mail依赖报错问题解决

    这篇文章主要介绍了SpringBoot导入mail依赖报错问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • springboot中使用过滤器,jsoup过滤XSS脚本详解

    springboot中使用过滤器,jsoup过滤XSS脚本详解

    这篇文章主要介绍了springboot中使用过滤器,jsoup过滤XSS脚本详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12

最新评论