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
_コンストラクターを手動でコーディングでき、Builderがそれを介して呼び出し、その中でinit
を呼び出すことができることを知っています。
しかし、私のクラスではたまに新しいフィールドが時々追加されるため、これは次善のソリューションです。これは、コンストラクタも変更することを意味します。
試行錯誤の末、適切な解決策を見つけました。生成ビルダーを拡張し、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;
}
}
}
Foo
では、コンストラクターを手動で追加し、初期化を行い、@Builder
コンストラクタで。あなたはすでにこれを知っていることを知っていますが、それは正しい解決策だと思います。とにかくビルダーでコードを使用したいので、パラメーターを追加することを忘れないでください。
開示:私はロンボクの開発者です。
私は同じ問題に出くわしました。しかし、さらに、メソッドbuildOptional()
をビルダーに追加して、必要になるたびにOptional.of(Foo)
を繰り返さないようにしたかったのです。チェーンされたメソッドはFooInternalBuilder
オブジェクトを返すため、これは以前に投稿されたアプローチでは機能しませんでした。 buildOptional()
をFooInternalBuilder
に入れると、Builder
でinit()
メソッドの実行が失敗します...
また、個人的には、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
_アノテーションがもたらす完全な標準機能を保持するこれを解決策として共有する前に問題を解決したとしても。それは少し短く、(私にとって)Nice機能を追加します。
これは私にとっては機能しますが、完全なソリューションではありませんが、すばやく簡単です。
@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
}
}