所以我知道在Java中,当你有一个静态方法时,你应该用格式ClassName.method()
来调用它,而不是使用与实例方法相同的结构,即:
ClassName myObject = new ClassName();
myObject.method();
但是,如果您这样做,它仍然是有效的代码并且可以工作。让我们说我决定在有问题的方法是静态的情况下这样做,并进行以下设置:
public SuperClass {
public static int foo(int x) {
return x;
}
}
public SubClass extends SuperClass {
public static int foo(int x) { // Overriding foo() in SuperClass
return x + 1;
}
}
public MyDriver {
public static void main(String[] args) {
SuperClass myObject = new SubClass(); // Upcasting.
System.out.println(myObject.foo(5)); // This should polymorphically print 6
}
}
然而,在屏幕上打印的是5而不是6.为什么?
答案 0 :(得分:5)
静态方法仅适用于它们所定义的类,并且不能覆盖它们。
当您致电myObject.foo(5)
时,您实际上正在调用SuperClass.foo(5)
,因为您将myObject
声明为SuperClass
,无论您是否将其实例化为一个。
调用静态方法的正确方法是直接从声明的类中调用它,因此如果要调用SubClass.foo()
,必须从显式调用它声明SubClass
个实例(意思是没有向上转播),或者您需要像这样调用SubClass.foo()
。
简单的答案是,从实例调用静态方法的方法是从声明的类型调用那些相同的方法而不是实例类型。
我不确定这一点,但如果将代码编译成字节代码,实际的静态方法调用实际上会编译成对声明类型的直接调用,我不会感到惊讶。
编辑:一个upvote把我的注意力带回了这个,我清理了解释,使其更清晰,并修复了一些可以忽略不计的语法错误。我希望这有助于未来的读者。
答案 1 :(得分:1)
静态方法不依赖于实例,它们属于类而只属于类,实际上如果你有一个静态方法,你总是可以访问一个唯一的实例。
myObject.foo(5)
只是一种捷径,你真正在做的是
SuperClass.foo(5)
答案 2 :(得分:1)
使用类的实例来调用该类的静态方法是您应该避免的,因为它可能会导致混淆。如果需要以多态方式调用任何方法,请将其设为实例方法。你不能多态调用静态方法。调用SuperClass调用的原因是因为它是编译时myObject的明显类。在以下场景中也可以看到这种效果:
public void doSomething(SuperClass param) {
System.out.println("SuperClass");
}
public void doSomething(SubClass param) {
System.out.println("SubClass");
}
public void test() {
SuperClass myObject = new SubClass();
doSomething(myObject);
}
如果调用test(),将打印SuperClass
。
答案 3 :(得分:0)
静态方法被JVM视为全局,它们根本不绑定到对象实例。顺便说一句,您只能重载静态方法,但不能覆盖。因此,请检查"Oracle Documentation for Overriding and Hiding Documents"。
使用与超类方法相同的签名定义方法:
----------------------------------------- 超类实例方法 超类静态方法
子类实例方法 覆盖 生成编译时错误
子类静态方法 生成编译时错误 隐藏