非静态字段初始化

时间:2016-09-19 01:30:21

标签: java collections initialization spock lombok

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

@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实例。我像这样运行spock测试到intellij2016

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()   
     }

这里的问题是,当调试这个测试时,我注意到它(在刺激方法中)使用null的Synchronized列表时抛出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循环

1 个答案:

答案 0 :(得分:1)

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

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

那是issue 916。不完全是一个错误,只是一个令人惊讶的行为。你最好只使用@Builder用于不可变的,没有问题的地方以及你真正需要它的地方。

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