Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the Java compiler allowed to be flow sensitive for static calls?

Tags:

java

jls

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?

like image 241
Jochen Avatar asked Oct 07 '22 05:10

Jochen


2 Answers

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.

like image 170
m0skit0 Avatar answered Oct 12 '22 11:10

m0skit0


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.

like image 40
Joop Eggen Avatar answered Oct 12 '22 10:10

Joop Eggen