HelterSkelter HelterSkelter - 3 months ago 10
Java Question

Subclass final static initialization prior to superclass class intialization?

I couldn't find any specific SO post referring to this specific case, so I'd like to ask what I think is a yes/no question.

Here's JLS §12.4.2 (Java SE 8), listing 6-7:



  1. [...] Then,
    initialize the static fields of C which are constant variables
    (§4.12.4, §8.3.2, §9.3.1).

  2. Next, if C is a class rather than an interface, and its superclass has not yet been initialized, then let SC be its superclass [...] For each S in the list [ SC, SI1, ..., SIn ], recursively perform this entire procedure
    for S. If necessary, verify and prepare S first. [...]




My question: Does it mean that final static variable of a subclass is initialized before the static initialization of the superclass (assuming the final static is initialized as part of its declaration)?

Answer

The answer is it might be so. The key part is a constant word meaning.

Consider this code

class Foo {
    public static final int FOO_VALUE = 1000;

    static {
        System.err.println("FOO Bar.BAR_VALUE=" + Bar.BAR_VALUE);
    }
}

class Bar extends Foo {
    public static final int BAR_VALUE = 2000;

    static {
        System.err.println("BAR Foo.FOO_VALUE=" + Foo.FOO_VALUE);
    }
}

The output of this program will be

FOO Bar.BAR_VALUE=2000
BAR Foo.FOO_VALUE=1000

In this case Bar static final variables are initialized before Foo static initialization. Both FOO_VALUE and BAR_VALUE are constants so javac may inline this fields.

But you can trick compiler by pretending that final variable is not a constant in this way

class Foo {
    public static final int FOO_VALUE = Integer.valueOf(1000).intValue();

    static {
        System.err.println("FOO " + Bar.BAR_VALUE);
    }
}

class Bar extends Foo {
    public static final int BAR_VALUE =  Integer.valueOf(2000).intValue();

    static {
        System.err.println("BAR " + Foo.FOO_VALUE);
    }
}

And output will be

FOO Bar.BAR_VALUE=0
BAR Foo.FOO_VALUE=1000

So Foo static initializer is finished before static final Bar.BAR_VALUE was initialized.

Comments