Let's say I have a class
class A{
public final static TreeMap<String,String> tmap = new TreeMap<>();
int x;
static{
tmap.put("x:I", "Hello");
}
}
and I create a subclass
class B extends A{
long y;
static{
tmap.put("y:J","World");
}
}
If I now write some code to check the static initialisers:
class Main{
public static void main (String[] args){
B b = new B();
for(String v : b.tmap.values()){
System.out.println(v);
}
}
}
I know both entries must be in tmap
because A
must get loaded, eventually, for B
's super call at the very latest.
But if I'm reading When does static class initialization happen? correctly, I cannot assume that the Hello
value is put into the map first all the times because tmap
is final.
So if ordering were important (say if I knew there's a chance some values may be updated/overwritten further down the hierachy), do I need to remove the final
modifier?
Or is there something else already enforcing "proper" static initialiser ordering?
Static initialization is always done for the super class before the child is initialized, if you have multiple static initializer blocks, they are executed in order. (Edit: Thanks to Holger for pointing out that this does not have to be directly when the class is loaded).
In your example, B extends A, and the classloader therefore has to load A before B. Thus, the static initializer of A ist executed first.
This has nothing to do with the final modifier. What the other thread probably refers to is that if the compiler can perform constant folding( https://www.javaworld.com/article/2076060/build-ci-sdlc/compiler-optimizations.html), the class from which the constant is taken will not be static initialized (as the reference is replaced at compile time).