使用Lombok @Builder注解导致默认值无效的问题

目录
  • @Builder注解导致默认值无效
    • 原因分析
  • lombok@Builder忽略属性默认值的坑点
    • 1. 简单使用
    • 2. 默认值问题
    • 3. 修改属性值

@Builder注解导致默认值无效

使用Lombok注解可以极高的简化代码量,比较好用的注解除了@Data之外,还有@Builder这个注解,它可以让你很方便的使用builder模式构建对象,但是今天发现@Builder注解会把对象的默认值清掉。

像下面这段代码,会导致对象的name属性变为null:

public class BuilderTest {
    @lombok.Builder
    @lombok.Data
    private static class Builder {
        private String name = "1232";
    }
    @Test
    public void test() {
        Builder builder = Builder.builder().build();
        System.out.println(builder.getName());
    }
}
---打印结果---
null

那么不想让这个默认值被清除,就只能用另外一个注解来对属性进行设置:@lombok.Builder.Default

示例代码如下:

public class BuilderTest {
    @lombok.Builder
    @lombok.Data
    private static class Builder {
        @lombok.Builder.Default
        private String name = "1232";
    }
    @Test
    public void test() {
        Builder builder = Builder.builder().build();
        System.out.println(builder.getName());
    }
}
---打印结果---
1232

需要注意的是@lombok.Builder.Default这个注解是后来才有的,目前已知的是1.2.X没有,1.6.X中有这个注解。

原因分析

使用@Builder注解的代码如下:

@lombok.Builder
class Example {
    private String name = "123";
}

Lombok会生成如下代码:

class Example {
    private String name;
    private Example(String name) {
        this.name = name;
    }
    public static ExampleBuilder builder() {
        return new ExampleBuilder();
    }
    public static class ExampleBuilder {
        private String name;
        private ExampleBuilder() {}
        public ExampleBuilder name(String name) {
            this.name = name;
            return this;
        }
        @java.lang.Override public String toString() {
            return "Example(name = " + name + ")";
        }
        public Example build() {
            return new Example(name);
        }
    }
}

很显然,ExampleBuilder的name没有默认值,导致build之后的Example的name是Null值。

lombok@Builder忽略属性默认值的坑点

1. 简单使用

他这个@Builder注解,相比之前的编辑器自动生成的getter setter的优点在哪呢?

看下面的使用例子

package com.lxk.lombok; import com.lxk.model.Bird; import java.util.Date;
/** * 测试@Builder * * @author LiXuekai on 2019/5/13 */public class BuilderTest {
public static void main(String[] args) {
Bird bird = new Bird("12", "34", new Date(), "红色皮肤", "巨大无比", 18, "典韦", "不序列化的字段,是不会被转json输出的");
Bird build = Bird.builder().dog1("12").dog2("34").birthday(new Date())
.color("红色皮肤").size("巨大无比").age(18)
.name("典韦").deserialize("不序列化的字段,是不会被转json输出的").build();
System.out.println(build.toString());
System.out.println(bird.toString());
}}

运行结果:

它相比编辑器生成的getter setter的优点:

1,代码很清晰,可读。可以很明确的知道,你的每一个属性的设置,

2,还有就是链式表达式,一串的就给set属性了,不需要写n行代码,之前自动生成的getter和setter,都需要写一个对象,然后再一个个的去点每一个属性的设置方法,

我例子里面的那个全参数构造方法,乍一看,看不出来每个参数是啥意思,但是下面的builder就很清楚的知道设置的都是啥。

代码使用的model bean的代码

package com.lxk.model;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/** * 鸟 * * @author LiXuekai on 2018/10/25 */
@Data@NoArgsConstructor@AllArgsConstructor@Builderpublic class Bird implements Serializable {
    private static final long serialVersionUID = 1L;
@JSONField(ordinal = 6, name = "内容是json字符串的属性", jsonDirect = true)
private String dog1;
@JSONField(ordinal = 5, name = "内容是json字符串的属性,对比下差异")
private String dog2;
/**     * ordinal,默认值为0,不用设置啦。     */
@JSONField(ordinal = 4, name = "生产日期", format = "yyyy年MM月dd日 HH时mm分ss秒")
private Date birthday;     @JSONField(ordinal = 3, name = "颜色")
private String color;     @JSONField(ordinal = 2, name = "体型大小")
private String size;     @JSONField(ordinal = 1, name = "年龄")
private int age;
/**     * 反序列化false,那么在反序列化的时候,就不会把json的值转给对象的这个属性。     */
@JSONField(name = "名称", deserialize = false)
private String name;
/**     * 不序列化此属性字段,那么在转json的时候,就不会在json中出现     */
@JSONField(ordinal = 7, name = "不序列化的属性字段", serialize = false)
private String deserialize;
}

2. 默认值问题

注意:默认值的情况。

如果原来的model bean 的属性是设置有默认值的,比如下面的age属性

然后,运行结果

@Builder默认是不支持默认值设置,或者说,自动忽略了model里面设置的默认值。

怎么让他支持默认值的设置。

在有默认值的属性上使用这个注解:@Builder.Default

要是你的这个default不存在,那是因为你使用的这个Lombok的版本太低了,试着升级到1.18.4及以上。我使用的是1.18.8版本。

3. 修改属性值

在model上加上这个注解参数:@Builder(toBuilder = true)

然后使用的时候,使用toBuilder()方法拿到builder

这个给人的感觉,类似String的replace()方法,他不是直接修改原来的对象,而是将结果以新的对象返回,所以,我们这儿需要个对象接收修改之后的返回值。

上面的执行结果,也可以看出来,修改过之后,原来的对象的值并没有变化,但是新接收的这个对象是修改后的值

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

(0)

相关推荐

  • Java中lombok的@Builder注解的解析与简单使用详解

    Lombok中@Builder用法 1.建造者模式简介:Builder 使用创建者模式又叫建造者模式.简单来说,就是一步步创建一个对象,它对用户屏蔽了里面构建的细节,但却可以精细地控制对象的构造过程. 2.注解类Builder.java注释: * The builder annotation creates a so-called 'builder' aspect to the class that is annotated or the class  * that contains a mem

  • Lombok同时使⽤@Data和@Builder踩坑总结

    目录 问题背景 Lombok @Data和@Builder分别单独分析用法 解决方法 Lombok原理 总结 问题背景 Lombok使⽤ 同时使⽤@Data和@Builder ,构建无参构造器报错!编译不通过.如下图: Lombok @Data和@Builder分别单独分析用法 Lombok使⽤@Data可以⽣成⽆参构造和类⾥⾯所有属性的getter/setter⽅法.可以简化我们代码的开发.(需要安装Lombok插件和引⼊Lombok依赖). 例如下⾯的⼀个实体类,引⼊Lombok后,可以⾃动

  • 聊聊Lombok中的@Builder注解使用教程

    目录 Lombok中的@Builder注解的使用 作用 引入依赖 第二步给实体类加上@Builder注解 第三步使用测试使用@Builder注解生成对象 实体类加上@Builder注解之后的编译结果 Lombok中的@Builder注解的使用 作用 @Builder注解的作用主要是用来生成对象,并且可以为对象链式赋值. 引入依赖 因为@Builder注解是lombok中的东西,所以第一步我们需要引入lombok的依赖,如下图: 第二步给实体类加上@Builder注解 第二步我们需要给我们的实体类

  • 使用Lombok @Builder注解导致默认值无效的问题

    目录 @Builder注解导致默认值无效 原因分析 lombok@Builder忽略属性默认值的坑点 1. 简单使用 2. 默认值问题 3. 修改属性值 @Builder注解导致默认值无效 使用Lombok注解可以极高的简化代码量,比较好用的注解除了@Data之外,还有@Builder这个注解,它可以让你很方便的使用builder模式构建对象,但是今天发现@Builder注解会把对象的默认值清掉. 像下面这段代码,会导致对象的name属性变为null: public class BuilderT

  • Java中Lombok @Value注解导致的variable not been initialized问题

    目录 背景 解决 背景 想要修改一个POJO类,在其中增加一个字段,但是增加以后就开始报错: 该类已经存在一个构造函数,为了不破坏该类原来的使用方式,于是重新写了一个构造方法,之前的构造函数未改动. 该类被Lombok的@Value注解修饰 解决 报错信息显示,变量未被初始化.于是主要排查是否有被初始化. 在重写的构造方法中,我已经对该变量进行了初始化. 不明所以,开始找不同,这个类中,唯一不熟悉的就是@Value注解,于是查看注解中的注释: /** * Generates a lot of c

  • 使用Lombok的@Builder注解带来的两大坑

    目录 一.@Data和@Builder导致无参构造丢失 二.@Builder注解导致默认值无效 三.分析原因 四.总结 一.@Data和@Builder导致无参构造丢失 单独使用@Data注解,是会生成无参数构造方法. 单独使用@Builder注解,发现生成了全属性的构造方法. @Data和@Builder一起用:我们发现没有了默认的构造方法.如果手动添加无参数构造方法或者用@NoArgsConstructor注解都会报错! 两种解决方法 1.构造方法加上@Tolerate 注解,让lombok

  • 关于element-ui 单选框默认值不选中的解决

    目录 element-ui 单选框默认值不选中 看我的下图吧 element-ui单选框组件,默认选中无效 element-ui 单选框默认值不选中 初次使用elementui单选框 发现一个问题 按照官网的案例 我cv过来 发现不对劲  怎么默认值不选中 如下图 ,难道我cv没cv正确??? 心里那个气啊,难道我发现了element-ui bug了???好的在cv一遍 还是发现默认值不选中,我就好 好看el-radio各个属性,依然百思不得其解,后来研究了一下,原来是自己的菜导致默认值不选中的

  • Spring Data JPA 设置字段默认值方式

    目录 Spring Data JPA设置字段默认值 Spring Data JPA设置字段默认值失败 Spring Data JPA设置字段默认值 在Column注解中写入以下两个属性,为什么自己查一下文档吧,即可实现字段默认值设置,并顺带解决save方法所生成的sql语句中自动填充字段为null的问题. 默认值无法更新,所以如果想在代码里修改字段默认值,你需要重新建表. @Column(insertable = false,columnDefinition = "int default 1&q

  • java 注解默认值操作

    我就废话不多说了,大家还是直接看代码吧~ package com.zejian.annotationdemo; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by wuzejian on 2017

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

    目录 前言 Lombok是什么 安装 对于eclipse 对于 IDEA QuickStart @Setter/@Getter @ToString exclude 参数 doNotUseGetters 参数 includeFieldNames参数 callSuper 参数 @NonNull @EqualsAndHashCode 参数 @Data @Cleanup @NoArgsConstructor/@RequiredArgsConstructor/@AllArgsConstructor @Va

  • ExtJS 设置级联菜单的默认值

    前言 ExtJS在修改这样的页面上赋值是很方便的,在正文中1.2.1代码中可以看出,一行代码就可以搞定,但这是对于普通控件而言,如文本框.对于ComboBox可没这么简单... 版本 Ext JS Library 3.0.0 正文 一.问题 1.1 截图 1.2 代码 1.2.1 前端代码 复制代码 代码如下: <script type="text/javascript"> // function ExtStore(url) { return new Ext.data.St

随机推荐