オブジェクトがあります
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
}
そして、私は2つの方法でそれを初期化します
UserInfo ui = new UserInfo();
UserInfo ui2 = UserInfo.builder().build();
System.out.println("ui: " + ui.isEmailConfirmed());
System.out.println("ui2: " + ui2.isEmailConfirmed());
ここに出力されます
ui: true
ui2: false
ビルダーはデフォルト値を取得していないようです。プロパティに@Builder.Default
注釈を追加すると、オブジェクトは次のようになります
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
@Builder.Default
private boolean isEmailConfirmed = true;
}
コンソール出力です
ui: false
ui2: true
両方をtrue
にするにはどうすればよいですか?
私の推測では、それは不可能です(コードを削除していなければ)。しかし、なぜ必要なコンストラクタを実装しないのですか?ロンボクはあなたの生活を楽にすることを目的としており、何かがロンボクで動作しない場合は、昔ながらの方法でそれを行ってください。
@Data
@Builder
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
@Builder.Default
private boolean isEmailConfirmed = true;
public UserInfo(){
isEmailConfirmed = true;
}
}
コンソール出力:
ui: true
ui2: true
@Builder.Default
アノテーションが壊れている なので、まったく使用しません。ただし、次のアプローチを使用できます。
@Data
@NoArgsConstructor
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
@Builder
@SuppressWarnings("unused")
private UserInfo(int id, String nick, Boolean isEmailConfirmed) {
this.id = id;
this.nick = nick;
this.isEmailConfirmed = Optional.ofNullable(isEmailConfirmed).orElse(this.isEmailConfirmed);
}
}
これにより、次のことが保証されます。
isEmailConfirmed
は1か所でのみ初期化されるため、コードのエラーが発生しにくく、後で保守しやすくなります。UserInfo
クラスは、ビルダーまたは引数なしのコンストラクターを使用する場合と同じ方法で初期化されますつまり、条件はtrue
を保持します。
new UserInfo().equals(UserInfo.builder().build())
その場合、オブジェクトの作成は、作成方法に関係なく一貫しています。クラスをマッピングフレームワークまたはJPAプロバイダーで使用する場合、ビルダーで手動でインスタンス化するのではなく、背後で引数なしのコンストラクターを呼び出してインスタンスを作成するときに特に重要です。
アプローチ 上記 は非常に似ていますが、大きな欠点があります。 2つの場所でフィールドを初期化する必要があります。これにより、値の一貫性を保つ必要があるため、コードエラーが発生しやすくなります。
別の方法は、独自のgetter method overrideinglombok getterを定義することです:
@Data
@Builder
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
private Boolean isEmailConfirmed;
public Boolean getIsEmailConfirmed(){
return Objects.isNull(isEmailConfirmed) ? true : isEmailConfirmed;
}
}
私のアプローチは次のとおりです。
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
}
その後
UserInfo ui = new UserInfo().toBuilder().build();
カスタムコンストラクターと@Builder.Default
は、おそらく一緒には機能しません。
フレームワークの作成者は、@Builder
の二重の初期化を避けたいと考えています。
.builder()
メソッドでpublic static CLAZZ of(...)
を再利用します:
@Builder
public class Connection {
private String user;
private String pass;
@Builder.Default
private long timeout = 10_000;
@Builder.Default
private String port = "8080";
public static Connection of(String user, String pass) {
return Connection.builder()
.user(user)
.pass(pass)
.build();
}
public static Connection of(String user, String pass, String port) {
return Connection.builder()
.user(user)
.pass(pass)
.port(port)
.build();
}
public static Connection of(String user, String pass, String port, long timeout) {
return Connection.builder()
.user(user)
.pass(pass)
.port(port)
.timeout(timeout)
.build();
}
}
対応する議論を確認してください: https://github.com/rzwitserloot/lombok/issues/1347