Search code examples
javastaticstatic-initialization

Initialization of base classes in Java when accessing a static field


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?


Solution

  • 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.