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 to Super.greeting()
because s
is defined to be Super
and 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 instance s
is a Sub()
as you specified, so the non-static method Sub.name()
is called.
From Java official tutorials:
You can also refer to static fields with an object reference like
myBike.numberOfBicycles
but this is discouraged because it does not make it clear that they are class variables.
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.
It is not too java specific. Imagine your "intelligent" compilation with s.getClass().greeting()
in:
class A extends Sub {
static String greeting() { return "Allo"; }
}
class B extends Sub {
static String greeting() { return "Brrr"; }
}
Super s = condition? new A() : new B();
assert s.greeting.equals(Sub.greeting()); // If compiler cannot infer condition.
Should the compiler do that across more than one source? Out of libraries, where the source code might not be available.
I rather think the fallacy in java is, that s.greeting()
is allowed.
As there is no use for static inheritance, better not invent such a feature.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With