Here’s a brief example from the JLS section 8.4.8.2.
class Super {
static String greeting() { return "Goodnight"; }
String name() { return "Richard"; }
}
class Sub extends Super {
static String greeting() { return "Hello"; }
String name() { return "Dick"; }
}
class Test {
public static void main(String[] args) {
Super s = new Sub();
System.out.println(s.greeting() + ", " + s.name());
}
}
According to the discussion of the example, the output of running main() will be “Goodnight, Dick”. This is because static methods are called based on the static type of the variable/expression they are called on.
Here’s my question: Any even moderately flow-sensitive compiler could figure out that the type of any object stored in s at the time of the call must always be Sub, so if the compiler were allowed to use that information, even calling static methods could have some of the feel of dynamic binding. Why is this not allowed? Does Java have the express goal that every compiler produces bytecode that behaves exactly the same or is there some other reason?
In fact here
s.greeting()is equivalent toSuper.greeting()becausesis defined to beSuperand static methods do not care about class instances. They’re class-wide as you surely know. So it directly makes no sense to call a static method from a class instance. And of course the instancesis aSub()as you specified, so the non-static methodSub.name()is called.From Java official tutorials:
Allowing static methods to be class-instance wise would only make the code less readable, more arcane and harder to debug without really adding any useful feature.