为什么在使用默认构造函数创建对象时,Lombok的@Builder会删除默认字段值?

时间:2017-08-31 22:49:35

标签: java lombok

请考虑以下代码:

@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注释,它将按预期工作。为什么龙目岛这样工作?我希望在使用默认构造函数时将空ArrayList分配给list属性。

1 个答案:

答案 0 :(得分:2)

这是一个已知问题(12)。当您使用@Builder注释某个类时,它会预期&#34;#34;您将使用构建器来实例化该类。当您使用绕过构建过程的@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方法,并且使用no-agrs构造函数是&#34;损坏&#的唯一方法34;实例化。

正如在第二个链接中所解释的那样,原因是如果赋值表达式(在您的情况下为new ArrayList<>())成本很高,那么使用构建器将导致表达式执行两次,这是性能问题。解决方法是编写自己的no-args构造函数并在那里进行字段初始化。