Java 为什么是龙目山';使用默认构造函数创建对象时,s@Builder是否会删除默认字段值?

Java 为什么是龙目山';使用默认构造函数创建对象时,s@Builder是否会删除默认字段值?,java,lombok,Java,Lombok,考虑以下代码: @RunWith(JUnit4.class) public class TestClass { @Test public void builderTest() throws Exception { List<Object> list = new LombokBuilderTest().list; assertNotNull(list); } } @NoArgsConstructor @AllArgsConst

考虑以下代码:

@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<>();
}
@RunWith(JUnit4.class)
公共类TestClass{
@试验
public void builderTest()引发异常{
List List=new LombokBuilderTest().List;
assertNotNull(列表);
}
}
@诺尔格构装师
@AllArgsConstructor
@建筑商
LombokBuilderTest类{
@Builder.Default
列表=新的ArrayList();
}
即使
list
属性有默认值,测试也会失败。如果您对
@Builder
注释进行注释,它将按预期工作。为什么龙目山是这样工作的?使用默认构造函数时,我希望将空的
ArrayList
分配给
list
属性。

这是一个已知问题(,)。当您使用
@Builder
注释一个类时,“预期”您将使用该生成器来实例化该类。使用绕过构建过程的
@noargsconstuctor
时会出现问题

为您的示例生成的代码如下所示:

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);
    }
}
LombokBuilderTest类{
公共静态类LombokBuilderTestBuilder{
私人名单;
私有布尔列表$set;
LombokBuilderTestBuilder(){}
公共LombokBuilderTestBuilder列表(最终列表){
this.list=列表;
list$set=true;
归还这个;
}
公共LombokBuilderTest构建(){
返回新的LombokBuilderTest((list$set?list:LombokBuilderTest.$default$list());
}
@凌驾
公共字符串toString(){
返回(((“LombokBuilderTest.LombokBuilderTestBuilder(list=“+this.list)+”);
}
}
名单;
私有静态列表$default$List(){
返回新的ArrayList();
}
公共静态LombokBuilderTestBuilder(){
返回新的LombokBuilderTestBuilder();
}
公共LombokBuilderTest(){}
公共LombokBuilderTest(最终列表){
this.list=列表;
}
公共静态void main(字符串[]args){
List List=new LombokBuilderTest().List;
系统输出打印项次(列表);
}
}
如您所见,您的初始化值已从字段声明移动到
$default$list
方法,使用no agrs构造函数是“损坏”实例化的唯一方法


正如在第二个链接中所解释的,原因是如果赋值表达式(
new ArrayList()
)代价高昂,那么使用生成器将导致表达式执行两次,这是一个性能问题。解决方法是编写自己的无参数构造函数并在那里进行字段初始化。

这不应该是
LombokBuilderTest.builder().build().list