探究lombok-03-@Builder使用
Java 8
org.springframework.boot 2.7.3
lombok 1.18.24
Eclipse Version: 2022-09 (4.25.0)
--ben发布于博客园
上一篇:探究lombok-02-类继承
https://www.cnblogs.com/luo630/p/16941903.html
注,本文测试结果的 LombokMain.java 的代码与上一篇相同。ben发布于博客园
0、序章
使用 @Builder 后,可以使用 链式编程 方式构建对象(一般方法是使用 new)。ben发布于博客园
示例代码:UserBuilderVO类
import java.util.Date;
import java.util.List;
import lombok.Builder;
@Builder
public class UserBuilderVO {
private Integer id;
private String name;
private List<String> tags;
private Date createTime;
}
1、仅@Builder
只使用 @Builder 的类分析结果:
测试:class=class com.lib.webdemo.vo.UserBuilderVO
----
prtClasses: length=1
内部类: com.lib.webdemo.vo.UserBuilderVO.UserBuilderVOBuilder, com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder, UserBuilderVOBuilder, com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder, modifiers=9
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo.UserBuilderVO, 参数数量:4, modifiers=0
----
prtFields: length=4
字段:id, type=class java.lang.Integer, modifiers=2
字段:name, type=class java.lang.String, modifiers=2
字段:tags, type=interface java.util.List, modifiers=2
字段:createTime, type=class java.util.Date, modifiers=2
----
prtMethods: length=1
方法名称:builder, 参数数量:0, modifiers=9
增加了一个内部类UserBuilderVOBuilder;
只有一个成员方法:builder。
UserBuilderVOBuilder 类分析结果(1):
test(UserBuilderVO.UserBuilderVOBuilder.class);
测试:class=class com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder
----
prtClasses: length=0
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder, 参数数量:0, modifiers=0
----
prtFields: length=4
字段:id, type=class java.lang.Integer, modifiers=2
字段:name, type=class java.lang.String, modifiers=2
字段:tags, type=interface java.util.List, modifiers=2
字段:createTime, type=class java.util.Date, modifiers=2
----
prtMethods: length=6
方法名称:name, 参数数量:1, modifiers=1
方法名称:toString, 参数数量:0, modifiers=1
方法名称:id, 参数数量:1, modifiers=1
方法名称:createTime, 参数数量:1, modifiers=1
方法名称:build, 参数数量:0, modifiers=1
方法名称:tags, 参数数量:1, modifiers=1
存在6个方法,其中一个为 build,用来生成 最终的 UserBuilderVO 对象。
链式编程 创建对象:
private static void testCreateUserBuilderVO() {
cs.accept("\n\n测试:testCreateUserBuilderVO...");
UserBuilderVO bvo = UserBuilderVO.builder()
.id(1)
.name("ben")
.tags(new ArrayList<>())
.createTime(new Date())
.build();
cs.accept("UserBuilderVO bvo=" + bvo);
}
测试结果:
测试:testCreateUserBuilderVO...
UserBuilderVO bvo=com.lib.webdemo.vo.UserBuilderVO@87aac27
直接输出对象,看不到对象里面各个属性的值;
也没有各个属性的getter方法,无法获取内部属性的值。
存在缺点:
无法用 链式编程 设置对象中 列表的值;(第3节)
对于 createTime,是否可以设置默认值?(第4节)
2、@Builder+@ToString+@Getter
给上面的 UserBuilderVO 类添加 @ToString、@Getter 注解。
类分析结果:多了 getter方法 和 ToString方法
prtMethods: length=6
方法名称:toString, 参数数量:0, modifiers=1
方法名称:getName, 参数数量:0, modifiers=1
方法名称:getId, 参数数量:0, modifiers=1
方法名称:builder, 参数数量:0, modifiers=9
方法名称:getCreateTime, 参数数量:0, modifiers=1
方法名称:getTags, 参数数量:0, modifiers=1
创建对象后输出结果:可以看到对象内部各个属性的值了
测试:testCreateUserBuilderVO...
UserBuilderVO bvo=UserBuilderVO(id=1, name=ben, tags=[], createTime=Mon Dec 05 19:23:44 CST 2022)
3、填充列表的值(@Singular)
在 第1节中,对 UserBuilderVOBuilder 类进行了分析,存在一个 tags方法。
此时,在链式编程中,需要提前建立一个列表作为参数传入。
要想在链式编程中设置tags属性的值,需要使用 @Singular 注解。
注,Singular adj. <语>单数的; <正>突出的; 奇特的; 非凡的; n. 单数形式(的词)。ben发布于博客园
(在第2节的基础上)给 UserBuilderVO 的 tags 属性添加 @Singular 注解。
UserBuilderVO 的类分析结果不变。
但 UserBuilderVOBuilder 的类分析结果(2) 存在下面的变化:
测试:class=class com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder
----
prtClasses: length=0
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder, 参数数量:0, modifiers=0
----
prtFields: length=4
字段:id, type=class java.lang.Integer, modifiers=2
字段:name, type=class java.lang.String, modifiers=2
字段:tags, type=class java.util.ArrayList, modifiers=2
字段:createTime, type=class java.util.Date, modifiers=2
----
prtMethods: length=8
方法名称:name, 参数数量:1, modifiers=1
方法名称:toString, 参数数量:0, modifiers=1
方法名称:id, 参数数量:1, modifiers=1
方法名称:createTime, 参数数量:1, modifiers=1
方法名称:build, 参数数量:0, modifiers=1
方法名称:tags, 参数数量:1, modifiers=1
方法名称:tag, 参数数量:1, modifiers=1
方法名称:clearTags, 参数数量:0, modifiers=1
多了 tag、clearTags 两个方法。
新的创建对象:链式编程 填充列表属性的值
private static void testCreateUserBuilderVO() {
cs.accept("\n\n测试:testCreateUserBuilderVO...");
UserBuilderVO bvo = UserBuilderVO.builder()
.id(1)
.name("ben")
// 旧 tags 方法
// .tags(new ArrayList<>())
// 新 tag方法
.tag("1").tag("2").tag("AAAA")
.createTime(new Date())
.build();
cs.accept("UserBuilderVO bvo=" + bvo);
}
测试结果:
测试:testCreateUserBuilderVO...
UserBuilderVO bvo=UserBuilderVO(id=1, name=ben, tags=[1, 2, AAAA], createTime=Mon Dec 05 19:43:06 CST 2022)
tags现在有值了。
填充Map
添加字段scores:
类分析结果:
测试:class=class com.lib.webdemo.vo.UserBuilderVO
----
prtClasses: length=1
内部类: com.lib.webdemo.vo.UserBuilderVO.UserBuilderVOBuilder, com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder, UserBuilderVOBuilder, com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder, modifiers=9
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo.UserBuilderVO, 参数数量:5, modifiers=0
----
prtFields: length=5
字段:id, type=class java.lang.Integer, modifiers=2
字段:name, type=class java.lang.String, modifiers=2
字段:tags, type=interface java.util.List, modifiers=2
字段:scores, type=interface java.util.Map, modifiers=2
字段:createTime, type=class java.util.Date, modifiers=2
----
prtMethods: length=13
方法名称:toString, 参数数量:0, modifiers=1
方法名称:getName, 参数数量:0, modifiers=1
方法名称:getId, 参数数量:0, modifiers=1
方法名称:builder, 参数数量:0, modifiers=9
方法名称:access$1, 参数数量:0, modifiers=4104
方法名称:access$2, 参数数量:0, modifiers=4104
方法名称:getTags, 参数数量:0, modifiers=1
方法名称:getCreateTime, 参数数量:0, modifiers=1
方法名称:getScores, 参数数量:0, modifiers=1
方法名称:$default$name, 参数数量:0, modifiers=10
方法名称:access$0, 参数数量:0, modifiers=4104
方法名称:$default$id, 参数数量:0, modifiers=10
方法名称:$default$createTime, 参数数量:0, modifiers=10
测试:class=class com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder
----
prtClasses: length=0
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder, 参数数量:0, modifiers=0
----
prtFields: length=9
字段:id$value, type=class java.lang.Integer, modifiers=2
字段:id$set, type=boolean, modifiers=2
字段:name$value, type=class java.lang.String, modifiers=2
字段:name$set, type=boolean, modifiers=2
字段:tags, type=class java.util.ArrayList, modifiers=2
字段:scores$key, type=class java.util.ArrayList, modifiers=2
字段:scores$value, type=class java.util.ArrayList, modifiers=2
字段:createTime$value, type=class java.util.Date, modifiers=2
字段:createTime$set, type=boolean, modifiers=2
----
prtMethods: length=11
方法名称:name, 参数数量:1, modifiers=1
方法名称:toString, 参数数量:0, modifiers=1
方法名称:id, 参数数量:1, modifiers=1
方法名称:tag, 参数数量:1, modifiers=1
方法名称:score, 参数数量:2, modifiers=1
方法名称:createTime, 参数数量:1, modifiers=1
方法名称:build, 参数数量:0, modifiers=1
方法名称:clearTags, 参数数量:0, modifiers=1
方法名称:clearScores, 参数数量:0, modifiers=1
方法名称:tags, 参数数量:1, modifiers=1
方法名称:scores, 参数数量:1, modifiers=1
测试代码及结果:
测试:testCreateUserBuilderVO...
UserBuilderVO bvo=UserBuilderVO(id=1, name=ben, tags=[1, 2, AAAA],
scores={数学=100, 语文=99, 科学=98, 文明=97}, createTime=Mon Dec 05 19:55:43 CST 2022)
4、设置默认值(@Builder.Default)
UserBuilderVO 对象的属性默认是null,可以使用 @Builder.Default 设置各个属性的默认值。ben发布于博客园
更新后的 UserBuilderVO:
@Builder
@Getter
@ToString
public class UserBuilderVO {
@Builder.Default
private Integer id = 2;
@Builder.Default
private String name = "罗峰";
@Singular
private List<String> tags;
@Builder.Default
private Date createTime = new Date();
}
类分析:
测试:class=class com.lib.webdemo.vo.UserBuilderVO
----
prtClasses: length=1
内部类: com.lib.webdemo.vo.UserBuilderVO.UserBuilderVOBuilder, com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder, UserBuilderVOBuilder, com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder, modifiers=9
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo.UserBuilderVO, 参数数量:4, modifiers=0
----
prtFields: length=4
字段:id, type=class java.lang.Integer, modifiers=2
字段:name, type=class java.lang.String, modifiers=2
字段:tags, type=interface java.util.List, modifiers=2
字段:createTime, type=class java.util.Date, modifiers=2
----
prtMethods: length=12
方法名称:toString, 参数数量:0, modifiers=1
方法名称:getName, 参数数量:0, modifiers=1
方法名称:getId, 参数数量:0, modifiers=1
方法名称:builder, 参数数量:0, modifiers=9
方法名称:$default$id, 参数数量:0, modifiers=10
方法名称:$default$name, 参数数量:0, modifiers=10
方法名称:access$1, 参数数量:0, modifiers=4104
方法名称:getTags, 参数数量:0, modifiers=1
方法名称:access$2, 参数数量:0, modifiers=4104
方法名称:access$0, 参数数量:0, modifiers=4104
方法名称:getCreateTime, 参数数量:0, modifiers=1
方法名称:$default$createTime, 参数数量:0, modifiers=10
测试:class=class com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder
----
prtClasses: length=0
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo.UserBuilderVO$UserBuilderVOBuilder, 参数数量:0, modifiers=0
----
prtFields: length=7
字段:id$value, type=class java.lang.Integer, modifiers=2
字段:id$set, type=boolean, modifiers=2
字段:name$value, type=class java.lang.String, modifiers=2
字段:name$set, type=boolean, modifiers=2
字段:tags, type=class java.util.ArrayList, modifiers=2
字段:createTime$value, type=class java.util.Date, modifiers=2
字段:createTime$set, type=boolean, modifiers=2
----
prtMethods: length=8
方法名称:name, 参数数量:1, modifiers=1
方法名称:toString, 参数数量:0, modifiers=1
方法名称:id, 参数数量:1, modifiers=1
方法名称:build, 参数数量:0, modifiers=1
方法名称:tag, 参数数量:1, modifiers=1
方法名称:clearTags, 参数数量:0, modifiers=1
方法名称:createTime, 参数数量:1, modifiers=1
方法名称:tags, 参数数量:1, modifiers=1
UserBuilderVO 的变化:方法里面多了 $default$ + 属性名、access$0~2。
UserBuilderVOBuilder 的变化:属性多了 属性名 + $value、属性名 + $set 格式的属性,少了 属性名 的属性、ben发布于博客园
创建对象:
cs.accept("\n\n测试:testCreateUserBuilderVO...");
UserBuilderVO bvo = UserBuilderVO.builder()
.build();
cs.accept("UserBuilderVO bvo=" + bvo);
测试结果:
测试:testCreateUserBuilderVO...
UserBuilderVO bvo=UserBuilderVO(id=2, name=罗峰, tags=[], createTime=Mon Dec 05 19:56:21 CST 2022)
更多测试:
@Singular 和 @Builder.Default 不可以同时存在。ben发布于博客园
疑问:
@Data 是否有什么更进一步的用法呢?ben发布于博客园
@Builder 的更多使用方式,可以看 参考资料#1 —— 来自官方
参考资料
1、官方文档-@Builder
https://projectlombok.org/features/Builder
讲的很详细。基本用法、高级用法。ben发布于博客园
2、Lombok 中@Builder 的使用
https://www.cnblogs.com/minmin123/p/14368725.html
posted @ 2021-02-03 18:27 keepsummer
3、
ben发布于博客园