有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

加载类时未初始化java静态变量

我有一个关于初始化的有趣问题。我有以下代码:

public class ErrorLookupProvider {  

private static final ErrorLookupProvider INSTANCE = new ErrorLookupProvider();

private  static Map<Long, List<String>> map = new HashMap<Long, List<String>>();

    private ErrorLookupProvider() {
        init();
    }

    private void init() {
        map.put(123L, ImmutableList.of("abc", "def"));
    }

    public static ErrorLookupProvider getInstance() {
        return INSTANCE;
    }
}

现在,当我调用ErrorLookupProvider.getInstance()时,我点击了一个NPE。init()内的映射未使用新的HashMap进行初始化

如果我将map的声明更改为final,那么我看到它已初始化。或者,即使我删除static并将其作为private Map<.....>的私有类变量,它也可以工作

我还没弄明白为什么会这样。有人能解释一下这里发生了什么吗


共 (3) 个答案

  1. # 1 楼答案

    切换映射和单例实例初始化的顺序

    静态初始化按照在源代码中遇到的顺序进行

    参见JLS 12.4.2 Detailed Initialization Procedure,第6步(第final部分)和第9步(第“顺序”部分)

    (单例实现和在ctor中处理静态,另一期。)

  2. # 3 楼答案

    补充:订单很重要。将静态映射的声明放在实例声明之前。Java编译器在排序方面有点愚蠢

    因为map是静态的,所以它在ErrorLookupProvider的所有实例之间共享。因此,在构造函数中使用它可能是一个错误。如果您创建了多个ErrorLookupProvider,您将多次冗余地添加到地图中。相反,在静态初始值设定项块中初始化它。或者,如果它真的意味着在ErrorLookupProvider的实例之间是独立的,那么不要将其设置为静态的