Sudoer
Sudoer

Reputation: 451

Static variable not initialized when class is loaded

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

Answers (3)

user949300
user949300

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

Dave Newton
Dave Newton

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

MaVRoSCy
MaVRoSCy

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

Related Questions