jls是否允许Java编译器对静态调用流敏感?
以下是JLS第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());
}
}
根据对示例的讨论,运行main()
的输出将是“晚安,迪克”。这是因为静态方法是根据调用它们的变量/表达式的静态类型来调用的
这里是我的问题:任何对流敏感度适中的编译器都可能发现,调用时存储在s
中的任何对象的类型必须始终为Sub
,因此如果允许编译器使用这些信息,即使调用静态方法也会有一些动态绑定的感觉。为什么这是不允许的?Java是否有明确的目标,即每个编译器生成行为完全相同的字节码,还是有其他原因
# 1 楼答案
实际上,这里
s.greeting()
等同于Super.greeting()
,因为s
被定义为Super
,静态方法不关心类实例。正如你肯定知道的,他们是全班的。因此,直接从类实例调用静态方法是没有意义的。当然,实例s
是您指定的Sub()
,因此调用了非静态方法Sub.name()
从Java official tutorials:
允许静态方法以类实例的方式运行只会使代码可读性变差,更加晦涩难懂,更难调试,而不会真正添加任何有用的特性
# 2 楼答案
它不太特定于java。想象一下您的
s.getClass().greeting()
智能编译:编译器应该跨多个源执行此操作吗?库外,源代码可能不可用
我认为java中的谬论是
s.greeting()
是允许的由于静态继承没有用处,最好不要发明这样的特性