我有一個有趣的初始化問題。我有以下代碼:加載類時未初始化靜態變量
現在,當我打電話ErrorLookupProvider.getInstance()
,我打了一個NPE。 init()
中的地圖未使用新的HashMap
進行初始化。
如果我將map
的聲明更改爲final,那麼我會看到它已初始化。或者,即使我刪除靜態並將其設置爲私有類變量private Map<.....>
也可以。
我一直無法弄清楚爲什麼會發生這種情況。有人可以解釋這裏發生了什麼嗎?
我有一個有趣的初始化問題。我有以下代碼:加載類時未初始化靜態變量
現在,當我打電話ErrorLookupProvider.getInstance()
,我打了一個NPE。 init()
中的地圖未使用新的HashMap
進行初始化。
如果我將map
的聲明更改爲final,那麼我會看到它已初始化。或者,即使我刪除靜態並將其設置爲私有類變量private Map<.....>
也可以。
我一直無法弄清楚爲什麼會發生這種情況。有人可以解釋這裏發生了什麼嗎?
從http://javapapers.com/core-java/explain-the-final-keyword-in-java/
引用被聲明爲final和未初始化叫做空白最終變量的變量。一個空白的final變量強制構造函數初始化它。
這就是爲什麼聲明爲final,當它被初始化
它甚至是有效的調用私人靜態最終ErrorLookupProvider INSTANCE = new ErrorLookupProvider(); 類的初始化首先是靜態變量,靜態塊,成員變量和構造函數。但是,在這種情況下,調用構造函數來初始化靜態變量甚至是有效的嗎? – Sudoer
是的,那很好。對你的代碼只是一個小小的評論,你可以用它作爲你的HashMap的聲明這個 private static Map
NO NO NO,當聲明爲final時,如果變量未由您初始化,構造函數將強制它初始化 – MaVRoSCy
新增:訂購事宜。在之前將您的靜態地圖的聲明放在INSTANCE的聲明中。 Java編譯器在訂購時有點愚蠢......
由於映射是靜態的,因此它在所有ErrorLookupProvider
實例中共享。因此,在構造函數中使用它可能是一個錯誤。如果您創建多個ErrorLookupProviders,則會多次冗餘地添加到地圖中。相反,請在靜態初始化塊中初始化它。或者,如果它確實是要在ErrorLookupProvider
的實例之間獨立,請不要將其設爲靜態。
切換映射和單例實例初始化的順序。
靜態初始化按其在源中遇到的順序發生。
請參閱JLS 12.4.2 Detailed Initialization Procedure步驟6(final
部分)和9(「訂單」部分)。
(單例的實現,並在構造函數靜碴,單獨的問題。)
哦!這是因爲靜力學的順序。如果我先把地圖放在地圖上,那我想也行。 這導致我問題 - 這甚至允許? private static final ErrorLookupProvider INSTANCE = new ErrorLookupProvider(); 通過排序,我通過調用構造函數初始化我的靜態變量。這意味着甚至在變量初始化之前調用構造函數。這個用法不正確嗎? Usualy中,init情況如下: 1.靜態成員 2.靜態塊 3.會員瓦爾 4.構造 現在,我想從1跳轉到4.如果這是不允許的? – Sudoer
@Sudoer是的,這就是我們所說的 - 順序重要:)當然它是允許的 - 它的工作原理,不是嗎? –
會,即使非長映射鍵編譯? –
我的錯誤,我錯過了123L – Sudoer