Who can explain what's going on?
public class MagicFinal {
public static void main(String[] args) {
System.out.println(A.s);
}
}
class A {
static {
System.out.println("class has been loaded");
}
public static final String s = "final";
public static final Integer i = 3;
}
Console :
final
What's it? I don't understand why the class has not been loaded, I know classes always load at the first call. Field s
is in pool of string, I see that final modifier is magic.
If I delete final modifier (public static String s = "final"
) I will get
Console :
class has been loaded
final
Note: I have changed field i
: public static final int i = 3;
and show it in console.
I got the same as in String situation. Why?
"final"
is a string literal and as such is a compile-time constant expression. The value of a static final
variable initialized with a compile-time constant expression is directly hardcoded into the class which references it, and no reference is made to the originating class. Therefore the initialization of the originating class does not occur.
As a side point, please note the distinction between class loading and class initialization: only the latter's occurrence is precisely specified by the JLS. Class loading can happen at any time.
This is what is written in Java Language Specification {8.3.2.1 Initializers for Class Variables}. This must answer your question
One subtlety here is that, at run time, static variables that are final and that
are initialized with compile-time constant values are initialized first. This also
applies to such fields in interfaces (§9.3.1). These variables are “constants” that
will never be observed to have their default initial values (§4.12.5), even by devious
programs. See §12.4.2 and §13.4.9 for more discussion.