首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用Lombok的@Builder 注解时,属性有默认值,会有什么坑🥶

使用Lombok的@Builder 注解时,属性有默认值,会有什么坑🥶

作者头像
崔认知
发布2025-02-26 12:48:59
发布2025-02-26 12:48:59
45300
代码可运行
举报
文章被收录于专栏:nobodynobody
运行总次数:0
代码可运行

在 java 中使用 Lombok的注解@Builder时,对象属性有默认值时会碰到默认值不会生效的坑。

Lombok 测试版本 1.18.28:

示例代码:

代码语言:javascript
代码运行次数:0
运行
复制
package com;


import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;


@Getter
@Setter
@ToString
@EqualsAndHashCode
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Demo {

   private String name;
   private boolean bTest1 = true;
   private Boolean bTest2 = true;


   public static void main(String[] args) {
      Demo demo = new DemoBuilder().build();
      System.out.println("lombok Builder 生成的对象: "+demo);
      System.out.println("默认构造函数生成的对象:  "+new Demo());
   }
}

代码中使用Lombok 的@Builder 注解生成的DemoBuilder,生成一个对象:

看一下对象中的属性默认值,使用DemoBuilder(第一行)与java默认构造函数(第二行)new对象后有什么不同结果:

使用DemoBuilder构造的java对象属性初始化完全和java的默认构造函数初始化的不一样,非常坑。

要想弄明白怎么回事,只能去看Lombok的@Builder是如何编译生成java代码(可跳过直接看重点截图):

代码语言:javascript
代码运行次数:0
运行
复制
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com;

import java.io.PrintStream;

public class Demo {
    private String name;
    private boolean bTest1 = true;
    private Boolean bTest2 = true;

    public static void main(String[] args) {
        Demo demo = (new DemoBuilder()).build();
        System.out.println("lombok Builder 生成的对象: " + demo);
        PrintStream var10000 = System.out;
        Demo var10001 = new Demo();
        var10000.println("默认构造函数生成的对象:  " + var10001);
    }

    public static DemoBuilder builder() {
        return new DemoBuilder();
    }

    public String getName() {
        return this.name;
    }

    public boolean isBTest1() {
        return this.bTest1;
    }

    public Boolean getBTest2() {
        return this.bTest2;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setBTest1(boolean bTest1) {
        this.bTest1 = bTest1;
    }

    public void setBTest2(Boolean bTest2) {
        this.bTest2 = bTest2;
    }

    public String toString() {
        String var10000 = this.getName();
        return "Demo(name=" + var10000 + ", bTest1=" + this.isBTest1() + ", bTest2=" + this.getBTest2() + ")";
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Demo)) {
            return false;
        } else {
            Demo other = (Demo)o;
            if (!other.canEqual(this)) {
                return false;
            } else if (this.isBTest1() != other.isBTest1()) {
                return false;
            } else {
                Object this$bTest2 = this.getBTest2();
                Object other$bTest2 = other.getBTest2();
                if (this$bTest2 == null) {
                    if (other$bTest2 != null) {
                        return false;
                    }
                } else if (!this$bTest2.equals(other$bTest2)) {
                    return false;
                }

                Object this$name = this.getName();
                Object other$name = other.getName();
                if (this$name == null) {
                    if (other$name != null) {
                        return false;
                    }
                } else if (!this$name.equals(other$name)) {
                    return false;
                }

                return true;
            }
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof Demo;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        result = result * 59 + (this.isBTest1() ? 79 : 97);
        Object $bTest2 = this.getBTest2();
        result = result * 59 + ($bTest2 == null ? 43 : $bTest2.hashCode());
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

    public Demo() {
    }

    public Demo(String name, boolean bTest1, Boolean bTest2) {
        this.name = name;
        this.bTest1 = bTest1;
        this.bTest2 = bTest2;
    }

    public static class DemoBuilder {
        private String name;
        private boolean bTest1;
        private Boolean bTest2;

        DemoBuilder() {
        }

        public DemoBuilder name(String name) {
            this.name = name;
            return this;
        }

        public DemoBuilder bTest1(boolean bTest1) {
            this.bTest1 = bTest1;
            return this;
        }

        public DemoBuilder bTest2(Boolean bTest2) {
            this.bTest2 = bTest2;
            return this;
        }

        public Demo build() {
            return new Demo(this.name, this.bTest1, this.bTest2);
        }

        public String toString() {
            return "Demo.DemoBuilder(name=" + this.name + ", bTest1=" + this.bTest1 + ", bTest2=" + this.bTest2 + ")";
        }
    }
}

Lombok的@Builder注解生成的 DemoBuilder构造函数如下:

就是一个java的普通对象,属性都来自我们自己写的对象,但是属性都是默认值初始化,所以我们使用new DemoBuilder().build()生成的对象,属性字段都是默认值。

Lombok提供了注解@Builder.Default,可以解决上面的问题(可跳过直接看重点截图):

代码语言:javascript
代码运行次数:0
运行
复制
package com;


import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;


@Getter
@Setter
@ToString
@EqualsAndHashCode
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Demo {

   private String name;

   @Builder.Default
   private boolean bTest1 = true;

   @Builder.Default
   private Boolean bTest2 = true;


   public static void main(String[] args) {
      Demo demo = new DemoBuilder().build();
      System.out.println("lombok Builder 生成的对象: "+demo);
      System.out.println("默认构造函数生成的对象:  "+new Demo());
   }
}

在属性上使用注解@Builder.Default:

我们可以下生成的java代码实现方式(可跳过直接看重点截图):

代码语言:javascript
代码运行次数:0
运行
复制
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com;

import java.io.PrintStream;

public class Demo {
    private String name;
    private boolean bTest1;
    private Boolean bTest2;

    public static void main(String[] args) {
        Demo demo = (new DemoBuilder()).build();
        System.out.println("lombok Builder 生成的对象: " + demo);
        PrintStream var10000 = System.out;
        Demo var10001 = new Demo();
        var10000.println("默认构造函数生成的对象:  " + var10001);
    }

    private static boolean $default$bTest1() {
        return true;
    }

    private static Boolean $default$bTest2() {
        return true;
    }

    public static DemoBuilder builder() {
        return new DemoBuilder();
    }

    public String getName() {
        return this.name;
    }

    public boolean isBTest1() {
        return this.bTest1;
    }

    public Boolean getBTest2() {
        return this.bTest2;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setBTest1(boolean bTest1) {
        this.bTest1 = bTest1;
    }

    public void setBTest2(Boolean bTest2) {
        this.bTest2 = bTest2;
    }

    public String toString() {
        String var10000 = this.getName();
        return "Demo(name=" + var10000 + ", bTest1=" + this.isBTest1() + ", bTest2=" + this.getBTest2() + ")";
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Demo)) {
            return false;
        } else {
            Demo other = (Demo)o;
            if (!other.canEqual(this)) {
                return false;
            } else if (this.isBTest1() != other.isBTest1()) {
                return false;
            } else {
                Object this$bTest2 = this.getBTest2();
                Object other$bTest2 = other.getBTest2();
                if (this$bTest2 == null) {
                    if (other$bTest2 != null) {
                        return false;
                    }
                } else if (!this$bTest2.equals(other$bTest2)) {
                    return false;
                }

                Object this$name = this.getName();
                Object other$name = other.getName();
                if (this$name == null) {
                    if (other$name != null) {
                        return false;
                    }
                } else if (!this$name.equals(other$name)) {
                    return false;
                }

                return true;
            }
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof Demo;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        result = result * 59 + (this.isBTest1() ? 79 : 97);
        Object $bTest2 = this.getBTest2();
        result = result * 59 + ($bTest2 == null ? 43 : $bTest2.hashCode());
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

    public Demo() {
        this.bTest1 = $default$bTest1();
        this.bTest2 = $default$bTest2();
    }

    public Demo(String name, boolean bTest1, Boolean bTest2) {
        this.name = name;
        this.bTest1 = bTest1;
        this.bTest2 = bTest2;
    }

    public static class DemoBuilder {
        private String name;
        private boolean bTest1$set;
        private boolean bTest1$value;
        private boolean bTest2$set;
        private Boolean bTest2$value;

        DemoBuilder() {
        }

        public DemoBuilder name(String name) {
            this.name = name;
            return this;
        }

        public DemoBuilder bTest1(boolean bTest1) {
            this.bTest1$value = bTest1;
            this.bTest1$set = true;
            return this;
        }

        public DemoBuilder bTest2(Boolean bTest2) {
            this.bTest2$value = bTest2;
            this.bTest2$set = true;
            return this;
        }

        public Demo build() {
            boolean bTest1$value = this.bTest1$value;
            if (!this.bTest1$set) {
                bTest1$value = Demo.$default$bTest1();
            }

            Boolean bTest2$value = this.bTest2$value;
            if (!this.bTest2$set) {
                bTest2$value = Demo.$default$bTest2();
            }

            return new Demo(this.name, bTest1$value, bTest2$value);
        }

        public String toString() {
            return "Demo.DemoBuilder(name=" + this.name + ", bTest1$value=" + this.bTest1$value + ", bTest2$value=" + this.bTest2$value + ")";
        }
    }
}

在生成的java类中,实现了两个获取属性默认值的静态方法:

生成的 DemoBuilder().build()方法,会判断是否设置了新值,如果没有,会用上面的静态方法获取赋值,从而解决了默认值的赋值问题:

虽然Lombok提供了注解@Builder.Default解决属性初始化的问题,但也带来了其他坑,且听下回分解。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-02-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 认知科技技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档