就够了
Posted 沛沛老爹
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了就够了相关的知识,希望对你有一定的参考价值。
背景
今天在联调接口的时候,前端同学说有个参数没有传值,导致报错了。
我看了下,原因是因为当前对象在mysql中的类型为text。
众所周知,text存储类型在MySQL8中是不能设置默认值的。
所以只能前置到代码中设定默认值。
使用过Lombok的都知道
设置默认值直接在属性字段上添加@Builder.default,然后设置默认值就可以了。
但是在编译的时候,错误出来了:
"无法将类 XX中的构造器 XX应用到给定类型"
错误示例代码
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class BuilderTest
private Integer code;
@Builder.default
private String name="";
错误分析
这个错误,根据字面上的意思是调用构造器的时候,属性参数没有构造成功。
根据刚刚加的那个字段来判断,应该是@Builder.default这个地方报错了。
@Builder注解默认用的是全参数构造函数,此时会导致无法new一个无参的构造对象出来。
既然不能默认构造无参,那就直接设定一个无参构造函数就好了。
解决方案
实现方式无非以下两种
直接构造一个无参对象
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class BuilderTest
private Integer code;
@Builder.default
private String name;
BuilderTest()
使用@NoArgsConstructor注解
使用后建立一个无参构造函数。
import lombok.Builder;
import lombok.Data;
@Data
@NoArgsConstructor
@Builder
public class BuilderTest
private Integer code;
@Builder.default
private String name="";
加上@NoArgsConstructor注解之后,你发现new对象的时候,红色波浪线没了。
但是编译的时候,你会发现错误依然在。依然在...
问题还是处在@Builder上面。
这个是为什么呢?
因为默认生成一个全参的构造函数。
但是使用了@NoArgsConstructor之后,全参构造函数没了。这样在编译的时候,如果加了@Builder的话会直接抛出”无法将类 BuilderTest中的构造器BuilderTest应用到给定类型“异常
所以,在这里你需要成对的使用ArgsConstructor注解,也就是@NoArgsConstructor和@AllArgsConstructor都要加上
import lombok.Builder;
import lombok.Data;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class BuilderTest
private Integer code;
@Builder.default
private String name="";
@AllArgsConstructor注解
这个注解的意思就是构造一个全参的构造函数。
为什么要加上@Builder注解和@Builder.Default注解?
我们先看下在@Builder下,代码编译后做了哪些改动。
@Builder详解
测试代码
先看下最简单的@Builder。@Builder使用的是Builder模式,Builder模式不熟悉的可以度娘一下。
import lombok.Builder;
import lombok.Data;
@Builder
public class BuilderTest
private Integer code;
private String name;
@Builder注解编译后代码
public class BuilderTest
private Integer code;
private String name;
BuilderTest(final Integer code, final String name)
this.code = code;
this.name = name;
public static BuilderTest.BuilderTestBuilder builder()
return new BuilderTest.BuilderTestBuilder();
public static class BuilderTestBuilder
private Integer code;
private String name;
BuilderTestBuilder()
public BuilderTest.BuilderTestBuilder code(final Integer code)
this.code = code;
return this;
public BuilderTest.BuilderTestBuilder name(final String name)
this.name = name;
return this;
public BuilderTest build()
return new BuilderTest(this.code, this.name);
public String toString()
return "BuilderTest.BuilderTestBuilder(code=" + this.code + ", name=" + this.name + ")";
代码分析
我们可以看到,编译之后的代码会在原来的代码基础上,增加一个builder方法和对应的一个XXBuilder的静态内部类。
public static BuilderTest.BuilderTestBuilder builder()
public static class BuilderTestBuilder
同时,在这里默认会生成一个全参的构造函数。但是却缺少了无参构造函数。
所以,如果你直接使用new BuilderTest() 因为没有无参构造函数,所以就会出问题了。
public class BuilderTest
private Integer code;
private String name;
BuilderTest(final Integer code, final String name)
this.code = code;
this.name = name;
...
只加上@NoArgsConstructor 后编译class
发现编译直接报上面的异常了。
再加上@AllArgsConstructor编译。
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BuilderTest
private Integer code;
//默认值注解
@Builder.Default
private String name="";
编译后代码如下
public class BuilderTest
private Integer code;
private String name;
private static String $default$name()
return "";
public static BuilderTest.BuilderTestBuilder builder()
return new BuilderTest.BuilderTestBuilder();
public BuilderTest()
this.name = $default$name();
public BuilderTest(final Integer code, final String name)
this.code = code;
this.name = name;
public static class BuilderTestBuilder
private Integer code;
private boolean name$set;
private String name$value;
BuilderTestBuilder()
public BuilderTest.BuilderTestBuilder code(final Integer code)
this.code = code;
return this;
public BuilderTest.BuilderTestBuilder name(final String name)
this.name$value = name;
this.name$set = true;
return this;
public BuilderTest build()
String name$value = this.name$value;
if (!this.name$set)
name$value = BuilderTest.$default$name();
return new BuilderTest(this.code, name$value);
public String toString()
return "BuilderTest.BuilderTestBuilder(code=" + this.code + ", name$value=" + this.name$value + ")";
错误定位(说明)
我们发现,编译后的代码为有默认值的属性,生成了String $default$name()方法。
使用了@Builder.Default之后,将会在默认无参构造函数中,给属性赋默认值。
private static String $default$name()
return "";
public BuilderTest()
this.name = $default$name();
如果去掉@Builder.Default后,编译结果如下
public class BuilderTest
private Integer code;
private String name = "";
public static BuilderTest.BuilderTestBuilder builder()
return new BuilderTest.BuilderTestBuilder();
public BuilderTest()
public BuilderTest(final Integer code, final String name)
this.code = code;
this.name = name;
public static class BuilderTestBuilder
private Integer code;
private String name;
BuilderTestBuilder()
public BuilderTest.BuilderTestBuilder code(final Integer code)
this.code = code;
return this;
public BuilderTest.BuilderTestBuilder name(final String name)
this.name = name;
return this;
public BuilderTest build()
return new BuilderTest(this.code, this.name);
public String toString()
return "BuilderTest.BuilderTestBuilder(code=" + this.code + ", name=" + this.name + ")";
我们可以看到,如果不使用@Builder.Default的话。
默认的无参构造函数里面是没有赋值操作的。
public BuilderTest()
所以如果你直接new对象的话,不适用@Builder.Default注解,正常情况下是没有默认值的。
你在保存数据到库的时候,当前属性的默认值不会带过去,只会给个null。
数据库没有设置默认值,使用MP进行存储的话,MySQL报insert的存储错误:当前字段没有default Value。
如果需要在DB中存储当前默认值的话,在使用了@Builder注解的类里,需要对类属性字段上加上@Builder.Default注解才能设置默认值。
总结
在类上添加@Builder注解,一般情况下,@NoArgsConstructor和@AllArgsConstructor都是成对出现的。
如果要想设置默认值的话,就必须在属性字段上增加@Builder.Default注解,new对象的时候set默认值。
当然如果你想在所有new对象的时候,使用builder方式来处理的话,那么@NoArgsConstructor和@AllArgsConstructor两个注解你可以不用。
这个个人不太建议,毕竟创建的类就是直接用来new的,如果Builder的话,要是对当前model类进行了修改,那么你需要到处去找使用了new当前对象的builder方法,然后去赋值,虽然前面看起来省了点布料,后面却需要不停的到处打补丁,中间浪费的成本实在太高了,不如一开始就一劳永逸。
这点也比较符合个人的做事风格,宁愿事后睡觉,不愿事中偷懒。毕竟古话说的好,出来混,迟早是要还的,只是时间早晚的事情。
以上是关于就够了的主要内容,如果未能解决你的问题,请参考以下文章