OfirD
OfirD

Reputation: 10460

Subclass final static initialization prior to superclass class initialization?

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)?

Upvotes: 3

Views: 128

Answers (1)

vsminkov
vsminkov

Reputation: 11250

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.

Upvotes: 2

Related Questions