Reputation: 451
I have an interesting question on initialization. I have the following code:
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;
}
}
Now when I call ErrorLookupProvider.getInstance()
, I hit an NPE. The map inside init()
is not initialized with the new HashMap
.
If I change the declaration of map
to be final, then I see that it is initialized. Or, even if I remove static and make it a private class variable as private Map<.....>
that works too.
I haven't been able to figure out why this happens. Can someone explain what is happening here?
Upvotes: 2
Views: 2496
Reputation: 15729
ADDED: Order matters. Put the declaration for your static map before the declaration of INSTANCE. The Java compiler is a bit stupid about ordering...
Since map is static, it is shared among all instances of ErrorLookupProvider
. Therefore, it is probably a mistake to play with it in the constructor. If you create multiple ErrorLookupProviders, you will redundantly add to the map many times. Instead, initilize it in a static initializer block. Or, if it is really meant to be independent between instances of ErrorLookupProvider
, don't make it static.
Upvotes: 2
Reputation: 160321
Switch the order of the map and singleton instance initializations.
Static initialization occurs in the order it's encountered in the source.
See JLS 12.4.2 Detailed Initialization Procedure, steps 6 (the final
part) and 9 (the "order" part).
(The singleton implementation and mucking with statics in a ctor, separate issue.)
Upvotes: 5
Reputation: 17859
quoting from http://javapapers.com/core-java/explain-the-final-keyword-in-java/
A variable that is declared as final and not initialized is called a blank final variable. A blank final variable forces the constructors to initialise it.
That is why when declared final it is initialised
Upvotes: 2