Lombokの@Builderアノテーションは何かと便利なのですが、プロパティへ値をセットするためのBuilderのメソッドを呼ばないと対応するフィールドが初期値(数値なら0, booleanならfalse, オブジェクトならnull
)になってしまいます。
このあたりの動きをv1.16.16で増えた@Builder.Default
で改善できるようになっています。
Builderで値をセットしなかった時の動きの確認
動作確認用にPerson1というクラスを用意して@Builder
を付与します。
Person1をBuilderを通じて2回生成します。1回目は全プロパティをセットしますが2回目はnameプロパティに値をセットしません。
import lombok.Builder; import lombok.Value; @Builder @Value public class Person1 { private final long id; private final String name; private final String description; }
■呼び出し側のコード
public final class Person1Client { public static void main(String[] args) { Person1 p1a = Person1.builder() .id(10L) .name("Taro") .description("name set person.") .build(); System.out.println("p1a#toString: " + p1a); // nameメソッドを呼ばない Person1 p1b = Person1.builder() .id(20L) .description("name not set person.") .build(); System.out.println("p1b#toString: " + p1b); } }
■実行結果
結果としてPerson1生成の2回目の呼び出しではnameの値がnullになっています。
p1a#toString: Person1(id=10, name=Taro, description=name set person.) p1b#toString: Person1(id=20, name=null, description=name not set person.)
対象オブジェクトの生成側が全プロパティをセットするのが必須ならいいですが、そうでないケースもあると思います。
そういう場合にはセットしなかったプロパティにはデフォルト値を入れておきたいところです。
デフォルト値をセットしたい時は
デフォルト値を入れておきたいという要望に応えるための方法として若干裏技的に以下リンク先のような方法が存在しています。
@Builder
アノテーションによって生み出されるコードを逆手に取ったような手法になっています。
@Builder.Default によるデフォルト値セット
Lombok
のv1.16.16から@Builder
でのデフォルト値指定のための@Builder.Default
が追加されました
デフォルト値をセットしたいフィールドに@Builder.Default
アノテーションを付与して、フィールドにデフォルト値をセットします。
本サンプルではnameフィールドに "<UNKNOWN>"という値をデフォルト値としてセットします
import lombok.Builder; import lombok.Value; @Builder @Value public class Person2 { private final long id; @Builder.Default private final String name = "<UNKNOWN>"; private final String description; }
■呼び出し側のコード
public final class Person2Client { public static void main(String[] args) { Person2 p2a = Person2.builder() .id(10L) .name("Taro") .description("name set person.") .build(); System.out.println("p1a#toString: " + p2a); // nameメソッドを呼ばない Person2 p2b = Person2.builder() .id(20L) .description("name not set person.") .build(); System.out.println("p2b#toString: " + p2b); } }
■実行結果
結果を見ると、Builderのnameメソッドを呼ばない場合はデフォルト値(<UNKNOWN>)がセットされていることが分かります
p1a#toString: Person2(id=10, name=Taro, description=name set person.) p2b#toString: Person2(id=20, name=<UNKNOWN>, description=name not set person.)
補足
実は私がこのエントリ書いてる段階では、IntelliJのIDE上では、@Builder.Default
を付与したフィールドへBuilderで値をセットするメソッドがコンパイルエラーになってしまいました。
ただし、ビルドや実行はできるので、Lombok
のpluginが対応できていないだけなのかもしれません。
EclipseであればIDE上も何もエラー出ませんでした。