有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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是否有明确的目标,即每个编译器生成行为完全相同的字节码,还是有其他原因


共 (2) 个答案

  1. # 1 楼答案

    实际上,这里s.greeting()等同于Super.greeting(),因为s被定义为Super,静态方法不关心类实例。正如你肯定知道的,他们是全班的。因此,直接从类实例调用静态方法是没有意义的。当然,实例s是您指定的Sub(),因此调用了非静态方法Sub.name()

    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.

    允许静态方法以类实例的方式运行只会使代码可读性变差,更加晦涩难懂,更难调试,而不会真正添加任何有用的特性

  2. # 2 楼答案

    它不太特定于java。想象一下您的s.getClass().greeting()智能编译:

    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.
    

    编译器应该跨多个源执行此操作吗?库外,源代码可能不可用

    我认为java中的谬论是s.greeting()是允许的

    由于静态继承没有用处,最好不要发明这样的特性