[email protected]注意すべき穴
2378 ワード
最近の開発では、エンティティークラスのbooleanフィールドをtrueとしてデフォルト化したいので、フィールド定義後にtrueとして値を付けます.また、クラスに@Builder注記があります.builder方式でインスタンスを作成するときにもtrueとしてデフォルト化したいと思っています.資料を見て、@Builder.Default注記が適切であることがわかりました.実際にコードを実行した後、builderモードではデフォルト値が有効になりますが、newを使用して得られたインスタンスのデフォルト値はfalseです.テストコードを貼って、はっきりしてください.
どうしてこんなことになったの?心の中で1万頭のアルパカが走った...
逆コンパイルされたPeopleコードを見てみましょう
最初から、コードのoldフィールドに初期値が付与されず、staticメソッド$default$oldが追加され、メソッドの戻り値が設定されたデフォルト値となります.次に、静的内部クラスPeopleBuilderのbuildメソッドでoldフィールドを判断し、値が設定されていない場合は$default$oldメソッドのデフォルト値をPeopleインスタンスに割り当てます.今やっと以前の困惑を理解して、@Builder.Defaultの実現原理を理解しました.
@Builder.Defaultで問題を解決できない以上、どうすればいいのでしょうか.
考えを変えて、インスタンスを初期化するとbooleanフィールドがfalseに初期化され、この特性を利用してフィールド名をnotOldに変更すればよい.コードは次のとおりです.
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.ToString;
public class testLombok {
public static void main(String[] args) {
People p1 = new People();
System.out.println(p1); //People(old=false)
People p2 = People.builder().build(); //People(old=true)
System.out.println(p2);
}
}
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
class People {
@Builder.Default
private boolean old = true;
}
どうしてこんなことになったの?心の中で1万頭のアルパカが走った...
逆コンパイルされたPeopleコードを見てみましょう
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import java.beans.ConstructorProperties;
class People {
private boolean old;
private static boolean $default$old() {
return true;
}
public static People.PeopleBuilder builder() {
return new People.PeopleBuilder();
}
public String toString() {
return "People(old=" + this.old + ")";
}
public People() {
}
@ConstructorProperties({"old"})
public People(boolean old) {
this.old = old;
}
public static class PeopleBuilder {
private boolean old$set;
private boolean old;
PeopleBuilder() {
}
public People.PeopleBuilder old(boolean old) {
this.old = old;
this.old$set = true;
return this;
}
public People build() {
return new People(this.old$set ? this.old : People.$default$old());
}
public String toString() {
return "People.PeopleBuilder(old=" + this.old + ")";
}
}
}
最初から、コードのoldフィールドに初期値が付与されず、staticメソッド$default$oldが追加され、メソッドの戻り値が設定されたデフォルト値となります.次に、静的内部クラスPeopleBuilderのbuildメソッドでoldフィールドを判断し、値が設定されていない場合は$default$oldメソッドのデフォルト値をPeopleインスタンスに割り当てます.今やっと以前の困惑を理解して、@Builder.Defaultの実現原理を理解しました.
@Builder.Defaultで問題を解決できない以上、どうすればいいのでしょうか.
考えを変えて、インスタンスを初期化するとbooleanフィールドがfalseに初期化され、この特性を利用してフィールド名をnotOldに変更すればよい.コードは次のとおりです.
public class People {
private boolean notOld;
}