当前位置: 首页 > 知识库问答 >
问题:

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

桓瀚
2023-03-14

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

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个答案

秋阳旭
2023-03-14

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

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

牧飞鹏
2023-03-14

引用http://javapapers.com/core-java/explain-the-final-keyword-in-java/

声明为最终且未初始化的变量称为空白最终变量。空白最终变量强制构造函数初始化它。

这就是为什么当宣布为最终版本时,它会被草签

糜雪峰
2023-03-14

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

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

参见JLS 12.4.2详细初始化程序、步骤6(最终部分)和步骤9(订单部分)。

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

 类似资料:
  • 问题内容: 我想知道为什么默认情况下C,C ++和Java中的确切静态变量初始化为零?为什么对局部变量不是这样? 问题答案: 为什么要对静态变量进行确定性初始化而对局部变量不进行初始化? 了解如何实现静态变量。 它们的内存在链接时分配,并且它们的初始值也在链接时提供。 没有运行时开销。 另一方面,用于局部变量的内存是在运行时分配的。堆栈必须增长。你不知道以前在那里。如果需要,可以清除该内存(将其清

  • 问题内容: 我想知道静态变量何时初始化为其默认值。加载类时,先创建(分配)静态变量,然后执行静态初始化程序和声明中的初始化是否正确?在什么时候给出默认值?这导致前向参考的问题。 另外,如果你可以参考“ 为什么没有及时初始化静态字段?”这一问题进行解释,尤其是Kevin Brock在同一网站上给出的答案。我不明白第三点。 问题答案: 从请参阅Java静态变量方法: 它是一个属于类而不属于对象(实例)

  • 我正在经历对我来说毫无意义的奇怪行为。以下程序(我试图将其简化为最小的示例)因而崩溃,因为为: 我希望它打印: 但是如果(可以通过取消对main方法的第一行的注释或对以下两行重新排序来完成),程序将正确终止。 我怀疑这个问题与Java类初始化顺序有关,但我在相关JLS部分中找不到任何解释。 所以,我的问题是:这到底是怎么回事?这是某种虫子还是我错过了什么? 我的JDK版本是1.8.0_111

  • 问题内容: 如何在Java中初始化类的私有静态成员。 尝试以下操作: 但是在创建类A的第二个对象然后调用f1()时,我得到了空指针异常。 问题答案: 初始化静态成员的首选方法是(如上所述) 或者对于更复杂的初始化代码,您可以使用静态初始化程序块:

  • 问题内容: 我有以下代码: 这给了我以下错误: 解析错误:语法错误,在第19行的/home/user/Sites/site/registration/inc/registration.class.inc中出现意外的’(’,期待’)’ 所以,我想我做错了什么…但是如果不那样做怎么办?如果我用常规字符串更改mktime内容,它将起作用。所以,我知道我能做到这一点 的那种 像.. 有人有指针吗? 问题答

  • 问题内容: 我想知道静态变量(在类中)何时出现在图片中(初始化)?是在实例构造函数首次调用之后还是在类加载之后?什么时候加载类? 问题答案: 哦,那很复杂。这取决于是否设置了标志,而标志(在C#中)又取决于是否有静态构造函数。更糟的是;在.NET 4中, 我相信 行为发生了变化,使其比以前更加“懒惰”。 坦白说,我不会在此处编写任何特定行为的代码。简单:只要您使用常规代码访问静态字段,它们就会在尝