返回顶部
首页 > 资讯 > 后端开发 > Python >lombok 子类中如何使用@Builder问题
  • 634
分享到

lombok 子类中如何使用@Builder问题

2024-04-02 19:04:59 634人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录lombok子类中如何使用@Builder子类使用lombok的@Builder注解正确姿势分析一下lombok子类中如何使用@Builder lombok大家都知道,在使用PO

lombok子类中如何使用@Builder

lombok大家都知道,在使用POJO过程中,它给我们带来了很多便利,省下大量写get、set方法、构造器、equal、toString方法的时间。除此之外,通过@Builder注解,lombok还可以方便的时间建造者模式。

但是,在使用@Builder过程中,我发现了一问题:子类的Builder对象没有父类的属性。这在使用上造成了一定的问题。

几番搜索,对于这个问题,找到了如下解法,解法的链接会放到文末。

1. 对于父类,使用@AllArgsConstructor注解

2. 对于子类,手动编写全参数构造器,内部调用父类全参数构造器,在子类全参数构造器上使用@Builder注解

通过这种方式,子类Builder对象可以使用父类的所有私有属性。

但是这种解法也有两个副作用:

1. 因为使用AllArgsConstructor注解,父类构造函数字段的顺序由声明字段的顺序决定,如果子类构造函数传参的时候顺序不一致,字段类型还一样的话,出了错不好发现

2. 如果父类字段有增减,所有子类的构造器都要修改

虽然有这两个副作用,但是这种解法是我找到的唯一一种解决子类使用@Builder,能使用父类属性的方式。

参考博客:

Lombok’s @Builder annotation and inheritance

副作用见博客评论

另,这个博主对lombok使用很有心得,我闲看还看到他另一篇涉及到@Builder的文章,将如何在使用@Builder的模式中,加入字段的默认值。因为使用了建造者模式,那么一般在类内声明字段的时候给字段默认值的方式就是无效的,需要在建造者上动手脚。

方式是:

1. 自定义静态内部类作为建造者,赋予默认值,再使用@Builder注解,这个时候lombok会补全已有的建造者类,进而使用默认值

2. 更新的lombok有@Builder.Default声明,注解在需要默认值的字段上即可。

在评论区也有这种方式的副作用讨论,可以一看。链接是:

Using Lombok’s @Builder annotation with default values

子类使用lombok的@Builder注解正确姿势

在实际开发中,有时候需要对子类使用lombok的 @Builder注解来使用builder模式构造该子类对象。

父类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Parent {
    private Long id;
 
    private String name;
}

子类

import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
 
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@Builder
public class Child extends Parent{
 
 
}

此时虽然在子类上添加了@Builder注解,但是由于子类没有属性,如下图所示,无法使用builder模式。

分析一下

通过阅读 lombok.Builder的源码,可知 @Builder 注解不仅可以用在类上,还可以用在构造函数上。

因此尝试如下写法:

@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@Builder
public class Child extends Parent {
 
    @Builder
    private Child(Long id, String name) {
        super(id, name);
    }
}

再次运行上面的单元测试,发现支持了 builder 模式,但是奇怪的是,单测不通过。

java.lang.AssertionError: 

Expected :1024

Actual   :null

因此我们观察一下 Child.class 反编译后的代码:

//
// Source code recreated from a .class file by IntelliJ idea
// (powered by Fernflower decompiler)
//
 
package com.chujianyun.libs.lombok;
 
public class Child extends Parent {
    private Child(Long id, String name) {
        super(id, name);
    }
 
    public static Child.ChildBuilder builder() {
        return new Child.ChildBuilder();
    }
 
    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Child)) {
            return false;
        } else {
            Child other = (Child)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                return super.equals(o);
            }
        }
    }
 
    protected boolean canEqual(final Object other) {
        return other instanceof Child;
    }
 
    public int hashCode() {
        int result = super.hashCode();
        return result;
    }
 
    public String toString() {
        return "Child()";
    }
 
    public Child() {
    }
 
    public static class ChildBuilder {
        private Long id;
        private String name;
 
        ChildBuilder() {
        }
 
        public Child build() {
            return new Child();
        }
 
        public String toString() {
            return "Child.ChildBuilder()";
        }
 
        public Child.ChildBuilder id(final Long id) {
            this.id = id;
            return this;
        }
 
        public Child.ChildBuilder name(final String name) {
            this.name = name;
            return this;
        }
    }
}

找到了原因,同时在子类和全参数的构造函数使用 @Builder 注解,会有 BUG,即最终的 build() 函数只是返回了空参的构造函数创建了一个 Child 对象,因此属性“采用 builder 方式设置的 id 和 name” 最终“丢失”。

那么如何解决这个问题呢?

我们再次回到@Builder 源码的注释上:

If a member is annotated, it must be either a constructor or a method. If a class is annotated,* then a private constructor is generated with all fields as arguments* (as if {@code @AllArgsConstructor(access = AccessLevel.PRIVATE)} is present* on the class), and it is as if this constructor has been annotated with {@code @Builder} instead.

可知,将其加到类上,相当于包含所有属性的私有构造方法,且构造方法上加上 @Builder 注解。

因此我们写的代码可能有冲突,我们修改如下:

import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
 
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
public class Child extends Parent {
 
    @Builder
    private Child(Long id, String name) {
        super(id, name);
    }
}

最终单测通过

我们观察一下此时编译后的代码:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
 
package com.chujianyun.libs.lombok;
 
public class Child extends Parent {
    private Child(Long id, String name) {
        super(id, name);
    }
 
    public static Child.ChildBuilder builder() {
        return new Child.ChildBuilder();
    }
 
    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Child)) {
            return false;
        } else {
            Child other = (Child)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                return super.equals(o);
            }
        }
    }
 
    protected boolean canEqual(final Object other) {
        return other instanceof Child;
    }
 
    public int hashCode() {
        int result = super.hashCode();
        return result;
    }
 
    public String toString() {
        return "Child()";
    }
 
    public Child() {
    }
 
    public static class ChildBuilder {
        private Long id;
        private String name;
 
        ChildBuilder() {
        }
 
        public Child.ChildBuilder id(final Long id) {
            this.id = id;
            return this;
        }
 
        public Child.ChildBuilder name(final String name) {
            this.name = name;
            return this;
        }
 
        public Child build() {
            return new Child(this.id, this.name);
        }
 
        public String toString() {
            return "Child.ChildBuilder(id=" + this.id + ", name=" + this.name + ")";
        }
    }
}

此时的build() 函数才是我们需要的状态。

从编译后的代码我们可以清晰地看出 lombok 通过@Builder 实现的 builder模式的核心逻辑。

即构造内部类,在内部类赋值属性,build时调用含有所有属性的构造方法创建对象。

更多细节可以仔细查看 @Builder 注解的源码和注释,查看官方的手册 https://projectlombok.org/features/Builder

总结:

遇到诡异的问题一定不要轻易放过。分析问题要有步骤,比如可以看源码中是否有说明,也可以看编译后的代码,还可以通过反汇编等,观察注解对类文件作出了哪些影响。还可以去看官方手册。

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

--结束END--

本文标题: lombok 子类中如何使用@Builder问题

本文链接: https://lsjlt.com/news/168053.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • lombok 子类中如何使用@Builder问题
    目录lombok子类中如何使用@Builder子类使用lombok的@Builder注解正确姿势分析一下lombok子类中如何使用@Builder lombok大家都知道,在使用PO...
    99+
    2024-04-02
  • 解决lombok父类和子类builder不兼容的问题
    目录遇到的问题排查和解决结尾遇到的问题 在写代码时,有时因为需要定义一些重复的参数,为了复用之前传参的DTO,会对原有的类进行继承,从而达到避免重复代码的效果。 但是,当父类中使用了...
    99+
    2024-04-02
  • 解决Lombok使用@Builder无法build父类属性的问题
    目录Lombok使用@Builder无法build父类属性问题描述解决方案使用示例lombok @Builder注解和build父类属性问题1、简介2、使用3、@Builder注解对...
    99+
    2024-04-02
  • Lombok注解之@SuperBuilder--解决无法builder父类属性问题
    目录一.老规矩二.判断是否为相同问题(@Builder注解不能 build 父类属性)三.@SuperBuilder注解1. 概念(需要注意您的Lombok版本)2. 如何解决无法b...
    99+
    2024-04-02
  • 使用Lombok@Builder注解导致默认值无效的问题
    目录@Builder注解导致默认值无效原因分析lombok@Builder忽略属性默认值的坑点1. 简单使用2. 默认值问题3. 修改属性值@Builder注解导致默认值无效 使用L...
    99+
    2024-04-02
  • 聊聊Lombok中的@Builder注解使用教程
    目录Lombok中的@Builder注解的使用作用引入依赖第二步给实体类加上@Builder注解第三步使用测试使用@Builder注解生成对象实体类加上@Builder注解之后的编译...
    99+
    2024-04-02
  • Lombok如何使用
    这篇文章主要讲解了“Lombok如何使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Lombok如何使用”吧! 简单的说,Lombok就是给你的主力机配...
    99+
    2024-04-02
  • Lombok在idea中如何使用
    这篇文章主要讲解了“Lombok在idea中如何使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Lombok在idea中如何使用”吧!一、什么是lombok  &nbs...
    99+
    2023-07-05
  • 如何解决升级IDEA后Lombok不能使用的问题
    本篇内容介绍了“如何解决升级IDEA后Lombok不能使用的问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!今天到工作室比较晚,在电脑前吃...
    99+
    2023-06-20
  • Lombok如何在Spring Boot中使用
    本篇文章给大家分享的是有关Lombok如何在Spring Boot中使用,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。springboot是什么springboot一种全新的编...
    99+
    2023-06-14
  • Lombok中@EqualsAndHashCode注解如何使用
    这篇文章主要介绍“Lombok中@EqualsAndHashCode注解如何使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Lombok中@EqualsAndHashCode注解如何使用”文章能帮...
    99+
    2023-07-05
  • Lombok使用@Tolerate实现冲突兼容问题
    目录使用@Tolerate实现冲突兼容例如,这样一个场景Lombok实验性注解之@Tolerate注解介绍使用场景实战演练使用@Tolerate实现冲突兼容 使用Lombok能够减少...
    99+
    2024-04-02
  • 如何解决Lombok注解不起作用的问题
    本篇内容介绍了“如何解决Lombok注解不起作用的问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Lombok注解不起作用场景:减少实体类...
    99+
    2023-06-20
  • Java的Lombok如何使用
    本篇内容主要讲解“Java的Lombok如何使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java的Lombok如何使用”吧!1)引入相应的maven包:<dependency>...
    99+
    2023-06-16
  • 如何在Java项目中使用Lombok
    本文章向大家介绍如何在Java项目中使用Lombok的基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,实现了面向对象理论,允许...
    99+
    2023-06-06
  • 如何使用Windows版 3D Builder
    要使用Windows版3D Builder,您可以按照以下步骤进行操作:1. 打开3D Builder应用程序:在Windows搜索...
    99+
    2023-09-14
    Windows
  • AtomicReference原子类如何在Java中使用
    AtomicReference原子类如何在Java中使用?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。AtomicReference介绍和函数列表AtomicReference...
    99+
    2023-05-31
    java concurrency ava
  • 使用lombok的@Data会导致栈溢出StackOverflowError问题
    目录问题复现原因分析Obj1的hashCode方法Obj2的hashCode方法解决方案最近撸代码发现一个问题,使用lombok的@Data会导致栈溢出StackOverflowEr...
    99+
    2022-11-21
    lombok栈溢出 lombok的@Data 栈溢出StackOverflowError
  • 如何用java解决兔子问题
    如何用java解决兔子问题,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。题目:古典问题:有一对兔子,从出生后第 3 个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生...
    99+
    2023-06-02
  • java中父类与子类之间的转换问题
    示例一父类强制转子类Father f = new Father(); Son s = (Father)f;//出错 ClassCastException分析:创建一个父类的实例,想要强制把父类对象转换成子类的,不行!通俗的想,真正当爹的永远...
    99+
    2018-08-17
    java 父类 子类 转换
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作