Java中不支持静态方法的动态多态性的原因



为什么Java不支持静态方法的动态多态性?如果答案是"静态方法不应该在实例上被调用,因此不需要在运行时解析方法调用",那么进一步的问题是"为什么Java允许我在实例上调用静态方法?"。为什么不简单地通过给出一些编译时错误来阻止用户直接在实例上调用该方法呢?

反过来说,如果Java支持静态方法的运行时多态性,会出现什么问题?

为什么Java允许我在实例上调用静态方法?

你的假设是错误的。它从不调用类的实例。它总是调用类。

尝试下面的示例代码,你永远不会得到NullPointerException

class ABC {
    public static void hello() {
        System.out.println("Hello");
    }
}
ABC abc = null;
abc.hello(); 

如果Java支持静态方法的运行时多态性,会出现什么问题?

当您在子类中重写方法时,就会出现多态性。因为静态方法属于类,所以没有重载静态方法的意义。因此,多态性总是只适用于属于类实例的实例方法。

静态方法是根据变量的类型而不是实例的类来解析的。这允许进行一些优化,因为要调用的确切方法是总是在编译时已知的。允许多态静态方法可以防止这种情况。

允许在实例上调用静态方法的结果如下:

class A {
    static void func() {}
}
class B extends A {
    static void func() {}
}
B b = new B();
A a = b;
b.func(); // calls B.func()
a.func(); // same instance, but calls A.func()

非常混乱,反直觉。根据静态方法的实现方式,允许在实例上调用静态方法是一个主要的设计缺陷,应该始终避免。

根据定义,静态方法不需要调用实例。通过允许多态调用,您需要一个实例,如果您需要一个实例来确定调用哪个方法,那么为什么该方法是静态的?

方法覆盖支持动态多态性。但是对于静态方法重写是不可能的,因为它会导致方法隐藏。因此静态方法不支持动态多态性。

我很高兴可以通过类的实例调用静态方法。它允许我不加限制地从实例调用该方法。如果我试图(合法但不合理地)通过将其称为实例,IDE会警告我。

public static void foo() {
    //yadda yadda
}
public void bar() {
    foo(); // this is legal
    MyClass.foo() // this is also legal, but would be necessary if I couldn't call it through the instance
}
// in some other class:
new MyClass().foo() // this is legal but silly and my IDE warns me about it

最新更新