在静态字段初始化期间使用Predicate时出现NullPointerException

时间:2016-08-22 14:18:22

标签: java java-8

有人可以在下面的示例代码中解释导致NPE的原因。这似乎与静态字段(特别是Predicate)的初始化方式有关,但我无法弄清楚发生了什么。

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Foo {
    public static List<Integer> stuff = doStuff();
    private static Predicate<Integer> bar = i -> i == 42;

    public static int howBigIsStuff(){
        return stuff.size();
    }

    private static List<Integer> doStuff(){
        // java.lang.NullPointerException 
        //    at java.util.Objects.requireNonNull(Objects.java:203)
        List<Integer> foo = Arrays.asList(1,2,42,42).stream()
                .filter(bar)
                .collect(Collectors.toList());
        return foo;
    }
}


import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.junit.Test;

public class FooTest {

    private static Predicate<Integer> bar = i -> i == 42;

    @Test
    public void test() {
        // This is fine
        List<Integer> foo = Arrays.asList(1,2,42,42).stream()
                .filter(bar)
                .collect(Collectors.toList());
        System.out.println(foo);    // [42, 42]

        Foo.howBigIsStuff();
    }
}

3 个答案:

答案 0 :(得分:2)

JLS-12.4.2。静态字段初始化的顺序很重要。字段按照它们在源中出现的顺序进行初始化。

因此,doStuff()调用时bar等于默认值null

答案 1 :(得分:1)

在初始化之前,您正在呼叫bar,请尝试以下操作:

public class Foo {
    private static Predicate<Integer> bar = i -> i == 42;
    public static List<Integer> stuff = doStuff();

    public static int howBigIsStuff() {
        return stuff.size();
    }

    private static List<Integer> doStuff() {
        // java.lang.NullPointerException 
        //    at java.util.Objects.requireNonNull(Objects.java:203)
        List<Integer> foo = Arrays.asList(1, 2, 42, 42).stream()
                .filter(bar)
                .collect(Collectors.toList());
        return foo;
    }
}

答案 2 :(得分:0)

初始化顺序为:

  • 执行方法doStuff(此处栏尚未初始化)
  • 东西变量的分配
  • bar变量的分配

以下是解决问题的方法:

public static List<Integer> stuff;
private static Predicate<Integer> bar;

static  {
    bar = i -> i == 42;
    stuff = doStuff();
}