Why doesn't Java allow overriding of static methods?

Why does Java prohibit code like this?

    public abstract class Singleton {
        public abstract static Singleton getInstance();
    }
    public class SingletonA extends Singleton {
        private static final Object monitor = new Object();
        private static volatile SingletonA INSTANCE;
        @Override
        public static SingletonA getInstance() {
            if (INSTANCE == null) {
                synchronized (monitor) {
                    if (INSTANCE == null) {
                        return new SingletonA();
                    }
                }
            }
            return INSTANCE;
        }
    }

I don’t see why it shouldn’t be allowed

You’re probably looking for method hiding (linked below).

Documentation is great:

If the underlying method is an instance method, it is invoked using dynamic method lookup as documented in The Java Language Specification, Second Edition, section 15.12.4.4; in particular, overriding based on the runtime type of the target object will occur.

The above means that when an object instance is initiated at runtime, its particular methods belong to it and it only. The instance methods it inherits get overriden at runtime.

Static methods belong to the class itself, and are available for the length of the program. That means they have to be in memory already and cannot be overriden at runtime (because what if you want to call the original method?). However if you use hiding, you create two static methods. This means that in the code they do not get overriden at runtime. You still get the functionality of the child class using the same method name as the parent.

https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html

Link to method hiding example below

1 Like

Sorry, but it doesn’t answer the why. By the same token, “what if you want to call the original instance method”?

The difference is that static methods are accessible beyond the scope of a class instance.

The only thing invoking instance methods are instances of that class, in a given run of a program, you can potentially create many instances at runtime (depending on what happens, user input etc.)… the fact that you can override these definitions is what allows for polymorphism. But for the override to happen it must be at run time.

Contrast with static things. They are at compile time (known before-hand, won’t change). You may make many instances of a class, but you have a contract that the static methods will not change (hence the name static, as in not moving). You can have a child class use the same static method name with hiding but you essentially have 2 separate static methods (again, because they cannot change at compile time and must be available in the program context).

This is common not just in java but in many other C-family languages.

You can also think of it like a public tool.
If tool X is publicly available and is only supposed to do Y, then someone comes and changes it to do Z without telling others, that would go against the point of it.

Don’t know if in example will help

public class Test {
    public static void main(String[] args) {
        // No instance necessary
        MyClass.myStaticMethod(); // relevant besides the context of foo/bar/baz
        foo = new MyClass();
        bar = new MyClass();
        foo.myInstanceMethod(); //only relevant for foo
        bar.myInstanceMethod(); //only relevant for bar
       // no instance of MyChildClass necessary for this call
        MyChildClass.myStaticMethod(); //by hiding you can get this to have a different effect as original static method
        baz = new MyChildClass();
        baz.myInstanceMethod(); //only relevant for baz, you can override this ok
     
    }
}

So it’s not so much that JVM prohibits it. It just goes against the definition of what it can do and how it does things. (if you say something won’t move, don’t move it, etc.). Do languages have to follow these paradigms? No. There are other families of languages with their own rules and so forth. And of course, we’re all free to dream and make our own languages with what should be the way ™.

and like I said before, you can get the same “effect” by the hiding technique. Except it won’t get overridden, you’ll just get an extra method (and there’s no ambiguity in which one will be invoked).

1 Like

No, I won’t have the same effect. Suppose I want to force concrete subclasses to provide their own implementation for an abstract static class. I can’t do that in Java. The only drawback I see is that it’s going to be a tiny bit slower in runtime (dynamic polymorphism costs)

Thanks for your effort, though