Initialization of base classes in Java when accessing a static field

38 Views Asked by At

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?

1

There are 1 best solutions below

2
Andy Turner On BEST ANSWER

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.