Why does Java enforce return type compatibility for overridden static methods?

匆匆过客 提交于 2019-12-02 21:08:44

Consider the following:

public class Foo {
  static class A {
    public static void doThing() {
      System.out.println("the thing");
    }
  }

  static class B extends A {

  }

  static class C extends B {
    public static void doThing() {
      System.out.println("other thing");
    }
  }

  public static void main(String[] args) {
    A.doThing();
    B.doThing();
    C.doThing();
  }
}

Run it! It compiles and prints out

the thing
the thing
other thing

Static methods sort of inherit -- in the sense that B.doThing is translated into a call to A.doThing -- and can sort of be overridden.

This seems like it was mostly a judgement call for the JLS. The most specific way the JLS seems to address this, though, is section 8.2, which simply doesn't say that static methods aren't inherited.

JLS 8.4.2 Method Signature, briefly:

Two methods have the same signature if they have the same name and argument types.

Nothing is said about staticness. Static methods can be called through an instance (or a null reference)--how should the method resolve if a subclass is referenced via a superclass declaration?

It is because in Java, a particular method is called based on the run time type of the object and not on the compile time type of it. However, static methods are class methods and hence access to them is always resolved during compile time only using the compile time type information. That is, what would happen if you could compile the above and use code like this

Foo bar = new Bar();
bar.frob();

Well, the JVM could probably be made to allow that, but let's talk about why it's a pretty bad idea from a compiler perspective.

The instance data (including which type the instance is) isn't something that is a simple problem to solve at compile time. Obviously it's well known at runtime. If I have a variable bar of type Bar, and I call s = bar.frob(), the compiler would need to reverse engineer what type bar is to see if the return value is acceptable. If determining the type at compile time is a super hard problem, this makes the compiler inefficient at best. At worst the answer is wrong and you get runtime errors that should have been caught at compile time.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!