The Java 21 specification states
A reference to a static field (§8.3.1.1) causes initialization of only the class or interface that actually declares it, even though it might be referred to through the name of a subclass, a subinterface, or a class that implements an interface.
and later
A class or interface will not be initialized under any other circumstance.
But when I have the following classes
public class Base {
static {
System.out.println("Base");
}
}
public class Derived extends Base {
static {
System.out.println("Derived");
}
public static int foo = 2;
}
public class Main {
public static void main(String[] args) {
System.out.println(Derived.foo);
}
}
The output of the program is
Base
Derived
2
It seems to me that the class Base
is initialized. Why is this the case? Doesn't the specification forbid this?
You are perhaps misunderstanding what "initialization of only the class or interface that actually declares it" means.
Consider this modification to your code:
public class Base { ... }
public class Derived extends Base { ... }
public class Derived2 extends Derived {
static {
System.out.println("Derived2");
}
}
public class Main {
public static void main(String[] args) {
System.out.println(Derived2.foo);
}
}
If you run this (Ideone), you will find it outputs:
Base
Derived
2
i.e. it doesn't print Derived2
.
In order to initialize a class, you have to initialize its superclasses. From JLS 12.4:
When a class is initialized, its superclasses are initialized (if they have not been previously initialized)
but Java doesn't need to initialize Derived2
in order to print a static symbol from Derived
.