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

Java中不支持静态方法的动态多态性的原因,java,polymorphism,static-methods,overriding,Java,Polymorphism,Static Methods,Overriding,为什么Java不支持静态方法的动态多态性? 如果答案是“静态方法不应该在实例上调用,因此不需要在运行时解析方法调用”,那么进一步的问题是“为什么Java允许我在实例上调用静态方法?”。为什么不通过给出一些编译时错误来阻止用户直接在实例上调用方法呢 反过来说,如果Java支持静态方法的运行时多态性,会出现什么问题 为什么Java允许我在实例上调用静态方法 你的假设是错误的。它从不调用类的实例。它总是上课 尝试下面的示例代码,您将永远不会得到NullPointerException class AB

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

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

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

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

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

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

ABC abc = null;
abc.hello(); 
如果Java支持静态方法的运行时多态性,会出现什么问题


当您在子类中创建方法时出现。由于静态方法属于类,所以重写静态方法并没有任何意义。因此,多态性总是只适用于属于类实例的实例方法。

我很高兴我可以通过类实例调用静态方法。它允许我无条件地从实例调用该方法。如果我试图(合法但非理性地)通过实例调用IDE,我的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

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

允许对实例调用静态方法的结果如下

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()
非常混乱,而且违反直觉。基于静态方法的实现方式,允许在实例上调用静态方法是一个主要的设计缺陷,应该始终避免


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

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

我假设您有实例(实例化了类)来调用静态方法。我不知道该类的任何实际对象。这是一个
null
引用;可以构造一个适用于静态方法的自一致性继承模型(在某些情况下可能很有用-例如,每个扩展
Tile
的类都有一个静态
initialiseGraphicsForClass
方法,并且您将一个类传递给一个方法)。所以问题依然存在;为什么不呢?这根本没有意义。由于类是在编译时确定的,因此不存在多态性的可能性。在实例上调用静态方法是(愚蠢的,依我看)编译器的一点小技巧。您真正要做的是对引用变量的声明类调用静态方法,这是在编译时确定的。我同意您的说法,但我的问题是为什么不阻止您不希望用户使用的功能。Smalltalk确实支持这一点,因此完全可以实现。我认为这只是为java做出的设计决策之一,老实说,我从未错过它。“然后进一步的问题是,‘为什么java允许我在实例上调用静态方法?’”允许这种语法是一个错误,但是现在不能更改它,因为这是一个突破性的更改。但是如果一个超类声明了一个名为foo的实例方法,会发生什么呢?应该调用哪个方法:实例方法还是静态方法?我相信实例方法的调用优先于静态方法。这意味着另一个人可能会改变超类,而没有意识到他们正在影响子类。我确实不赞成支持静态方法的动态多态性,但如果java支持实例上的静态方法调用,那么它应该完全支持它(就像实例方法一样)或者完全阻止用户对实例调用静态方法。