我有一个类,我想使用Lombok.Builder,我需要预处理一些参数。像这样:
@Builder
public class Foo {
public String val1;
public int val2;
public List<String> listValues;
public void init(){
// do some checks with the values.
}
}
通常我会在NoArg构造函数上调用init()
,但是对于生成的构建器,我无法这样做。有没有办法让生成的构建器调用此init
?例如,build()
会生成如下代码:
public Foo build() {
Foo foo = Foo(params....)
foo.init();
return foo;
}
我知道我可以手动编码all args
构造函数,构建器会通过它调用它,我可以在那里调用init
。
但这是一个次优解决方案,因为我的课程可能偶尔会添加新字段,这也意味着更改构造函数。
答案 0 :(得分:8)
经过多次试验和结束错误后,我找到了合适的解决方案:扩展生成构建器并自己调用init()
。
示例:
@Builder(toBuilder = true, builderClassName = "FooInternalBuilder", builderMethodName = "internalBuilder")
public class Foo {
public String val1;
public int val2;
@Singular public List<String> listValues;
void init() {
// perform values initialisation
}
public static Builder builder() {
return new Builder();
}
public static class Builder extends FooInternalBuilder {
Builder() {
super();
}
@Override public Foo build() {
Foo foo = super.build();
foo.init();
return foo;
}
}
}
答案 1 :(得分:5)
在@Builder
中,您可以手动添加构造函数,让它进行初始化,并将rsync -xyz --foo=bar some_files user@remote.com:remote_dir
放在构造函数上。我知道您已经知道这一点,但我认为这是正确的解决方案,您不会忘记添加参数,因为您确实想要在构建器中使用代码。
披露:我是一名lombok开发者。
答案 2 :(得分:4)
我偶然发现了同样的问题。但另外,我想向构建器添加一个方法buildOptional()
,以便在每次需要时不重复Optional.of(Foo)
。这不适用于之前发布的方法,因为链式方法返回FooInternalBuilder
个对象;并将buildOptional()
放入FooInternalBuilder
将错过init()
中的Builder
方法执行...
另外,我个人不喜欢2个构建器类的存在。
以下是我所做的事情:
@Builder(buildMethodName = "buildInternal")
@ToString
public class Foo {
public String val1;
public int val2;
@Singular public List<String> listValues;
public void init(){
// do some checks with the values.
}
/** Add some functionality to the generated builder class */
public static class FooBuilder {
public Optional<Foo> buildOptional() {
return Optional.of(this.build());
}
public Foo build() {
Foo foo = this.buildInternal();
foo.init();
return foo;
}
}
}
您可以使用以下主要方法进行快速测试:
public static void main(String[] args) {
Foo foo = Foo.builder().val1("String").val2(14)
.listValue("1").listValue("2").build();
System.out.println(foo);
Optional<Foo> fooOpt = Foo.builder().val1("String").val2(14)
.listValue("1").listValue("2").buildOptional();
System.out.println(fooOpt);
}
这样做让我们添加我想要的内容:
init()
方法,该方法在每个对象构建后自动执行init()
执行)@Builder
注释带来的标准功能即使你在我想分享这个解决方案之前解决了你的问题。它有点短,并添加了(对我而言)不错的功能。
答案 3 :(得分:0)
这对我有用,不是一个完整的解决方案,但快速简便。
@Builder
@AllArgsConstructor
public class Foo {
@Builder.Default
int bar = 42;
Foo init() {
// perform values initialisation
bar = 451; // replaces 314
return foo;
}
static Foo test() {
return new FooBuilder() // defaults to 42
.bar(314) // replaces 42 with 314
.build()
.init(); // replaces 314 with 451
}
}