Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I guarantee the order in which static initializers are run in Java?

I have a Set class (This is J2ME, so I have limited access to the standard API; just to explain my apparent wheel-reinvention). I am using my set class to create constant sets of things in classes and subclasses. It sort of looks like this...

class ParentClass
{
    protected final static Set THE_SET = new Set() {{
        add("one");
        add("two");
        add("three");
    }};
}


class SubClass extends ParentClass
{
    protected final static Set THE_SET = new Set() {{
        add("four");
        add("five");
        add("six");
        union(ParentClass.THE_SET); /* [1] */
    }};
}

All looks fine, except the line at [1] causes a null pointer exception. Presumably this means that the static initialiser in the subclass is being run before that of the parent class. This surprised me because I'd have thought it would run the static blocks in any new imports first, before running any in the instatiated subclass.

Am I right in this assumption? Is there any way to control or work around this behaviour?

Update:

Things are even stranger. I tried this instead (Note the 'new ParentClass()' line):

class ParentClass
{
    public ParentClass()
    {
        System.out.println(THE_SET);
    }

    protected final static Set THE_SET = new Set() {{
        add("one");
        add("two");
        add("three");
    }};
}


class SubClass extends ParentClass
{
    protected final static Set THE_SET = new Set() {{
        System.out.println("a");
        new ParentClass();
        System.out.println("b");
        add("four");
        System.out.println("c");
        add("five");
        System.out.println("d");
        add("six");
        System.out.println("e");
        union(ParentClass.THE_SET); /* [1] */
        System.out.println("f");
    }};
}

And the output is strange:

a
["one", "two", "three"]
b
c
d
e
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException

So ParentClass is initialised, but the subclass doesn't have access to it in its static initializer.

like image 707
izb Avatar asked Apr 27 '09 13:04

izb


People also ask

What is the order of execution of all static members?

Order of execution When you have all the three in one class, the static blocks are executed first, followed by constructors and then the instance methods.

Which static block will execute first?

The static blocks always execute first before the main() method in Java because the compiler stores them in memory at the time of class loading and before the object creation. Here, the compiler executes all the static blocks first, and after finishing the static block execution, it invokes the main() method.

What is true about static initializers in Java?

A Static Initialization Block in Java is a block that runs before the main( ) method in Java. Java does not care if this block is written after the main( ) method or before the main( ) method, it will be executed before the main method( ) regardless.

What should be the execution order if a class has a method static block instance block and constructor?

The execution order of the program is that the static block executes first, then instance block, and then constructor.


1 Answers

Is this what you are trying to accomplish? Or do you need a local implementation of the Set interface?

class ParentClass
{
    protected final static Set THE_SET;

    static {
        THE_SET = new HashSet();
        THE_SET.add("one");
        THE_SET.add("two");
        THE_SET.add("three");
    }
}


class SubClass extends ParentClass
{
    protected final static Set THE_SECOND_SET;

    static {
        THE_SECOND_SET = new HashSet();
        THE_SECOND_SET.add("four");
        THE_SECOND_SET.add("five");
        THE_SECOND_SET.add("six");
        union(ParentClass.THE_SET); /* [1] */
    }
}
like image 121
Elijah Avatar answered Sep 28 '22 16:09

Elijah