Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is a subclass' static initializer not invoked when a static method declared in its superclass is invoked on the subclass?

Given the following classes:

public abstract class Super {
    protected static Object staticVar;

    protected static void staticMethod() {
        System.out.println( staticVar );
    }
}

public class Sub extends Super {
    static {
        staticVar = new Object();
    }

    // Declaring a method with the same signature here, 
    // thus hiding Super.staticMethod(), avoids staticVar being null
    /*
    public static void staticMethod() {
        Super.staticMethod();
    }
    */
}

public class UserClass {
    public static void main( String[] args ) {
        new UserClass().method();
    }

    void method() {
        Sub.staticMethod(); // prints "null"
    }
}

I'm not targeting at answers like "Because it's specified like this in the JLS.". I know it is, since JLS, 12.4.1 When Initialization Occurs reads just:

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • ...

  • T is a class and a static method declared by T is invoked.

  • ...

I'm interested in whether there is a good reason why there is not a sentence like:

  • T is a subclass of S and a static method declared by S is invoked on T.
like image 632
Gerold Broser Avatar asked Sep 19 '14 20:09

Gerold Broser


People also ask

Which will be invoked first when we have both static blocks and static method?

If you want to execute static block you need to have Main method and, static blocks of the class get executed before main method.

Under what circumstances would a subclass need to override a superclass method?

When a method in a subclass has the same name, same parameters or signature, and same return type(or sub-type) as a method in its super-class, then the method in the subclass is said to override the method in the super-class.

Can you declare an overridden method to be static if the original method is not static?

No, we cannot override static methods because method overriding is based on dynamic binding at runtime and the static methods are bonded using static binding at compile time. So, we cannot override static methods. The calling of method depends upon the type of object that calls the static method.

Can we call super class static method in subclass?

Yes, you can call the methods of the superclass from static methods of the subclass (using the object of subclass or the object of the superclass).


2 Answers

Be careful in your title, static fields and methods are NOT inherited. This means that when you comment staticMethod() in Sub , Sub.staticMethod() actually calls Super.staticMethod() then Sub static initializer is not executed.

However, the question is more interesting than I thought at the first sight : in my point of view, this shouldn't compile without a warning, just like when one calls a static method on an instance of the class.

EDIT: As @GeroldBroser pointed it, the first statement of this answer is wrong. Static methods are inherited as well but never overriden, simply hidden. I'm leaving the answer as is for history.

like image 77
Dici Avatar answered Oct 27 '22 06:10

Dici


The JLS is specifically allowing the JVM to avoid loading the Sub class, it's in the section quoted in the question:

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.

The reason is to avoid having the JVM load classes unnecessarily. Initializing static variables is not an issue because they are not getting referenced anyway.

like image 39
Nathan Hughes Avatar answered Oct 27 '22 06:10

Nathan Hughes