2017-08-31 3 views
1

は、次のコードを考えてみましょう:なぜロンボクの@Builderは、デフォルトのフィールド値を削除しますか?

@RunWith(JUnit4.class) 
public class TestClass { 

    @Test 
    public void builderTest() throws Exception { 
     List<Object> list = new LombokBuilderTest().list; 
     assertNotNull(list); 
    } 
} 

@NoArgsConstructor 
@AllArgsConstructor 
@Builder 
class LombokBuilderTest { 
    @Builder.Default 
    List<Object> list = new ArrayList<>(); 
} 

listプロパティのデフォルト値があるにもかかわらず、テストが失敗しました。 @Builder注釈をコメントすると、期待通りに機能します。なぜロンボクはこのように動作しますか?私は、デフォルトコンストラクタを使用している場合、空ArrayListlistプロパティに割り当て持つことを期待します。

+0

それは 'LombokBuilderTest.builder(すべきではない)。構築()。list'? – chrylis

答えて

1

これは既知の問題(12)です。あなたは@Builderでクラスに注釈を付けるとき、それはあなたがクラスをインスタンス化するためにビルダーを使用したいという「期待される」のです。あなたが構築プロセスをバイパス@NoArgsConstructorを使用するときに問題が来ます。

ご例えば生成されたコードは、次のようなものになります。あなたが見ることができるように

class LombokBuilderTest { 

    public static class LombokBuilderTestBuilder { 
     private List<Object> list; 
     private boolean list$set; 

     LombokBuilderTestBuilder() {} 

     public LombokBuilderTestBuilder list(final List<Object> list) { 
      this.list = list; 
      list$set = true; 
      return this; 
     } 

     public LombokBuilderTest build() { 
      return new LombokBuilderTest((list$set ? list : LombokBuilderTest.$default$list())); 
     } 

     @Override 
     public String toString() { 
      return (("LombokBuilderTest.LombokBuilderTestBuilder(list=" + this.list) + ")"); 
     } 
    } 

    List<Object> list; 

    private static List<Object> $default$list() { 
     return new ArrayList<>(); 
    } 

    public static LombokBuilderTestBuilder builder() { 
     return new LombokBuilderTestBuilder(); 
    } 

    public LombokBuilderTest() {} 

    public LombokBuilderTest(final List<Object> list) { 
     this.list = list; 
    } 

    public static void main(String[] args) { 
     List<Object> list = new LombokBuilderTest().list; 
     System.out.println(list); 
    } 
} 

を、あなたの初期化された値は$default$listメソッドにフィールド宣言からを移動された無agrsコンストラクタをされて使用してインスタンス化を「壊す」唯一の方法です。

2番目のリンクで説明したように、割り当て式(あなたのケースではnew ArrayList<>())が高価な場合、ビルダを使用すると式が2回実行され、パフォーマンス上の問題が発生します。回避策は、独自の引数なしコンストラクタを作成し、そこでフィールドの初期化を行うことです。

関連する問題