2012-06-15 28 views
2

我有一个有趣的初始化问题。我有以下代码:加载类时未初始化静态变量

​​

现在,当我打电话ErrorLookupProvider.getInstance(),我打了一个NPE。 init()中的地图未使用新的HashMap进行初始化。

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

我一直无法弄清楚为什么会发生这种情况。有人可以解释这里发生了什么吗?

+0

会,即使非长映射键编译? –

+0

我的错误,我错过了123L – Sudoer

回答

2

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

引用被声明为final和未初始化叫做空白最终变量的变量。一个空白的final变量强制构造函数初始化它。

这就是为什么声明为final,当它被初始化

+0

它甚至是有效的调用私人静态最终ErrorLookupProvider INSTANCE = new ErrorLookupProvider(); 类的初始化首先是静态变量,静态块,成员变量和构造函数。但是,在这种情况下,调用构造函数来初始化静态变量甚至是有效的吗? – Sudoer

+0

是的,那很好。对你的代码只是一个小小的评论,你可以用它作为你的HashMap的声明这个 private static Map > map = new HashMap <>(); – MaVRoSCy

+0

NO NO NO,当声明为final时,如果变量未由您初始化,构造函数将强制它初始化 – MaVRoSCy

2

新增:订购事宜。在之前将您的静态地图的声明放在INSTANCE的声明中。 Java编译器在订购时有点愚蠢......

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

5

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

静态初始化按其在源中遇到的顺序发生。

请参阅JLS 12.4.2 Detailed Initialization Procedure步骤6(final部分)和9(“订单”部分)。

(单例的实现,并在构造函数静碴,单独的问题。)

+0

哦!这是因为静力学的顺序。如果我先把地图放在地图上,那我想也行。 这导致我问题 - 这甚至允许? private static final ErrorLookupProvider INSTANCE = new ErrorLookupProvider(); 通过排序,我通过调用构造函数初始化我的静态变量。这意味着甚至在变量初始化之前调用构造函数。这个用法不正确吗? Usualy中,init情况如下: 1.静态成员 2.静态块 3.会员瓦尔 4.构造 现在,我想从1跳转到4.如果这是不允许的? – Sudoer

+0

@Sudoer是的,这就是我们所说的 - 顺序重要:)当然它是允许的 - 它的工作原理,不是吗? –