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:
- [...] Then, initialize the static fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1).
- 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)?
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.