首页 > Python资料 博客日记
@Build 与 @SuperBuild 的区别
2025-01-16 18:30:06Python资料围观12次
优质博文:IT-BLOG-CN
一、@Builder
@Builder
是lombok
中的注解。可以使用builder()
构造的Person.PersonBuilder
对象进行链式调用,给所有属性依次赋值。
Person person1 = Person.builder()
.name("张三")
.age(20)
.build();
System.out.println(person1); // Person(name=张三, age=20)
System.out.println(Person.builder()); // Person.PersonBuilder(name=null, age=null)
文档中给了案例,在实体类上添加@Builder
后,实体类会被改造成如下的结构:
Before:
@Builder
class Example<T> {
private T foo;
private final String bar;
}
After:
class Example<T> {
private T foo;
private final String bar;
// 私有的全参数构造函数
private Example(T foo, String bar) {
this.foo = foo;
this.bar = bar;
}
// 返回一个重新构建的Builder对象
public static <T> ExampleBuilder<T> builder() {
return new ExampleBuilder<T>();
}
// 没一次都是放回一个构建后的对象
public static class ExampleBuilder<T> {
private T foo;
private String bar;
private ExampleBuilder() {}
public ExampleBuilder foo(T foo) {
this.foo = foo;
return this;
}
public ExampleBuilder bar(String bar) {
this.bar = bar;
return this;
}
@java.lang.Override public String toString() {
return "ExampleBuilder(foo = " + foo + ", bar = " + bar + ")";
}
public Example build() {
return new Example(foo, bar);
}
}
}
Builder
注解开发的源代码:
@Target({TYPE, METHOD, CONSTRUCTOR})
@Retention(SOURCE)
public @interface Builder {
// 内部注解 Default
@Target(FIELD) // @Target: 指定这个注解可以应用的程序元素类型。
@Retention(SOURCE)// @Retention: 指定这个注解的保留策略。SOURCE: 注解只在源代码中保留,编译时会被丢弃。
public @interface Default {}
// Builder 注解的属性
String builderMethodName() default "builder"; // 定义生成的 builder 方法的名称,默认为 "builder"。
String buildMethodName() default "build"; // 定义生成的 build 方法的名称,默认为 "build"。
String builderClassName() default ""; // 定义生成的 builder 类的名称,默认为空字符串。
boolean toBuilder() default false; // 指定是否生成一个 toBuilder 方法,默认为 false。
AccessLevel access() default lombok.AccessLevel.PUBLIC; // : 定义生成的 builder 方法的访问级别,默认为 lombok.AccessLevel.PUBLIC。
String setterPrefix() default ""; // 定义生成的 setter 方法的前缀,默认为空字符串。
// 内部注解 ObtainVia
@Target({FIELD, PARAMETER})
@Retention(SOURCE)
public @interface ObtainVia {
String field() default "";
String method() default "";
boolean isStatic() default false;
}
}
@Builder.Default
:使用@Builder.Default
设置默认值,构建对象时可以不用调用name()
方法。(调用后会覆盖默认值)
@Builder.Default
private String name = "zhangsan";
二、为什么要使用 @SuperBuilder
在涉及到继承相关的子父类字段时,如果使用@Builder
会出现编译错误:
// 第一个类
@Builder
public class Person{
private String name;
}
// 第二个类
@Builder
public class Man extends Person{
private String career;
}
编译报错:
无法将Person中的构造器 Person应用到给定类型;
需要: java.lang.String
找到: 没有参数
原因: 实际参数列表和形式参数列表长度不同
Man
构建的时候会去构建子类Person
,但是Person
由于加了@Builder
,没有无参构建函数;
public class Man extends Person {
private String career;
Man(final String career) {
this.career = career;
}
public static ManBuilder builder() {
return new ManBuilder();
}
public static class ManBuilder {
private String career;
ManBuilder() {
}
public ManBuilder career(final String career) {
this.career = career;
return this;
}
public Man build() {
return new Man(this.career);
}
public String toString() {
return "Man.ManBuilder(career=" + this.career + ")";
}
}
}
既然是没有无参构造函数,那么就在子类上添加无参构造函数@NoArgsConstructor
但是idea
提示错误,Lombok @Builder needs a proper constructor for this class
,那么再加上@AllArgsConstructor
,成功消除报错,但是编译报错,提示:
java: Man中的builder()无法覆盖Person中的builder()
返回类型Man.ManBuilder与Person.PersonBuilder不兼容
该错误是因为Man
类中的builder()
方法试图重写Person
类中的builder()
方法,但是返回类型不匹配导致的。Person
类的builder()
方法返回的是PersonBuilder
类型的对象。Man
类继承自Person
,但其builder()
方法返回的是ManBuilder
类型的对象。
在Java
中,子类的方法如果要重写父类的方法,那么子类方法的返回类型必须是父类方法返回类型的子类型或者相同类型。这里ManBuilder
和PersonBuilder
是两个独立的类型,不是继承关系,因此不符合Java
的重写规则。所以就需要使用到@SuperBuilder
三、@SuperBuilder
@Builder
注解无法解析父类的属性,而@SuperBuilder
可以读取父类的属性。使用时需要在子类和父类上都加上这个注解。
@SuperBuilder
public class Male extends Person{
}
@SuperBuilder
public class Person {
@Builder.Default
private String name = "zhangsan";
private Integer age;
@Singular("skillList")
private List<String> skillList;
}
@SuperBuilder(toBuilder=true)
:使用@SuperBuilder(toBuilder=true)
可以使用已有的对象构建新的对象,旧对象的属性值会被保留和覆盖。注意: 子类和父类都需要加上toBuilder=true
Male man = Male.builder()
.name("张三")
.age(20)
.build();
Male man2 = man.toBuilder()
.age(30)
.build();
四、@SuperBuilder 不能与 @NoArgsConstructor 直接共存
有时我们需要@NoArgsConstructor
无参构造函数,但如果直接与@SuperBuilder
一起使用,会遇到编译冲突,导致构造器生成失败。可以借助@NoArgsConstructor
的force
属性,强制生成无参构造函数:这样Lombok
会生成无参构造器,同时支持@SuperBuilder
。
@NoArgsConstructor(force = true)
@SuperBuilder
public class Example {
private final String field;
}
标签:
相关文章
最新发布
- 光流法结合深度学习神经网络的原理及应用(完整代码都有Python opencv)
- Python 图像处理进阶:特征提取与图像分类
- 大数据可视化分析-基于python的电影数据分析及可视化系统_9532dr50
- 【Python】入门(运算、输出、数据类型)
- 【Python】第一弹---解锁编程新世界:深入理解计算机基础与Python入门指南
- 华为OD机试E卷 --第k个排列 --24年OD统一考试(Java & JS & Python & C & C++)
- Python已安装包在import时报错未找到的解决方法
- 【Python】自动化神器PyAutoGUI —告别手动操作,一键模拟鼠标键盘,玩转微信及各种软件自动化
- Pycharm连接SQL Sever(详细教程)
- Python编程练习题及解析(49题)
点击排行
- 版本匹配指南:Numpy版本和Python版本的对应关系
- 版本匹配指南:PyTorch版本、torchvision 版本和Python版本的对应关系
- Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO
- 相关性分析——Pearson相关系数+热力图(附data和Python完整代码)
- Anaconda版本和Python版本对应关系(持续更新...)
- Python与PyTorch的版本对应
- Windows上安装 Python 环境并配置环境变量 (超详细教程)
- Python pyinstaller打包exe最完整教程