非静态字段初始化

Non static field initialization

我的问题是关于使用静态方法初始化非静态字段。 基本上我的代码是

@NoArgsConstructor
@Builder
public class MyClass implements Callable<MyResultClass>{{

        @Setter private MyService service;

        List<MyType> myList = 
        Collections.synchronizedList(new ArrayList<MyType>());

     //.... other fields methods and so on
    }

我在我的 spock 测试中发现 myList 在此语句之后(在每个方法调用中)为 null。我解决了在构造函数中初始化它但我无法弄清楚为什么它为空。谁能向我解释这种行为,如果可能的话,给我一些参考以更好地理解使用静态方法进行字段初始化? 谢谢

我同意你们所有人的看法,我不明白这里出了什么问题。我正在使用 lombok builder 来创建这个 Callable 实例。我 运行 对 intellij2016

进行了这样的 spock 测试
class InboundMessageListenerSpec extends Specification{
      private MyService service = Mock(MyService)

      given: 
      def myClassObject = MyClass.builder().service(service).build()
      ....other objects

      when:
      //stimulus that also starts the thread

      then:
      1 * service.myMethod()   
     }

这里的问题是,在调试此测试时,我注意到它在(在刺激方法中)使用空的同步列表时抛出 NullPointerException。

我尝试用正常的实例创建和字段注入替换构建器,并且所有工作都按方面进行。我需要调查 lombok 生成器的行为。

堆栈跟踪:

java.lang.NullPointerException: null
    at org.fw.adapters.secondary.NetworkInventoryDataAdapter.deleteCvlanRows(NetworkInventoryDataAdapter.java:111)
    at org.fw.kernel.flows.executors.StartMigrationExecutor.call(StartMigrationExecutor.java:114)
    at org.fw.kernel.flows.executors.StartMigrationExecutor.call(StartMigrationExecutor.java:34)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)

第 111 行是上面列表中的一个 foreach 循环

这是一个众所周知的问题。您正在使用 @Builder,允许您设置所有字段。它做到了。尝试 delombok 看看发生了什么。

我不确定细节,但大致是这样的: - 你的 @Builder 使用 @AllArgsContructor - 你没有在构建器中设置 myList,所以它保持 null - null 传递给您的 @AllArgsContructor - 谁将它复制到新创建的对象 (*)

那是 issue 916。不完全是一个错误,只是一个令人惊讶的行为。您最好只对不可变对象使用 @Builder,在没有问题和真正需要的地方。


(*) 在 Java 中,构造函数的代码在初始化表达式之后执行。