3

这些 OCA 练习题 (pdf)中的问题三:

abstract class Writer {
   public static void write() {
      System.out.println("Writing...");
   }
}

class Author extends Writer {
   public static void write() {
      System.out.println("Writing book");
   }
}

public class Programmer extends Writer {
   public static void write() {
      System.out.println("Writing code");
   }
   public static void main(String[] args) {
      Writer w = new Programmer();
      w.write();
   }
}

输出是Writing...

我不明白为什么。作为ProgrammeroverridesWriter的 write 方法,我认为它应该调用 inProgrammer而不是 in的方法Writer

为什么?

4

4 回答 4

5

这里你要明白两点。

在成员的情况下没有压倒一切的概念static。它们是简单static的,永远不会根据实例而改变。

并且static成员绑定到类而不是实例。因此,无论实例是什么,它们都会查看它们被调用并执行的类型。

于 2018-01-30T09:23:20.317 回答
2

引用的类型是Writer。您调用了一个未应用覆盖的静态方法 -Writer将调用来自 的方法。

该机制称为方法隐藏


看看这些案例:

new Programmer().write();             // code  [Programmer]
((Writer)new Author()).write();       // ...   [Writer]

new Author().write();                 // book  [Author]
((Writer)new Programmer()).write();   // ...   [Writer]

new Writer() {{}}.write();            // ...   [Writer]
于 2018-01-30T09:23:32.367 回答
1

众所周知,static方法不能被覆盖。如果我们尝试这样做,结果证明是方法隐藏。在上述情况下,类WriterProgrammer包含write()方法。

Programmer扩展Writer类并提供自己的write()方法实现时,它只是隐藏了Writer它的实现。

现在,在运行时,编译器只检查引用类型(因为它是一个静态方法,编译器并不关心为调用该方法而创建的对象。记住,静态方法是类方法)。因此,编译器检查并发现引用w是 type Writer,它会调用该方法的Writer版本write。如果方法不是static,那么您所期望的将是输出。

于 2018-01-30T09:38:03.163 回答
-1

自己找到了答案。

在 Java 中没有覆盖静态方法这样的事情。这就是为什么当您从超类引用调用静态方法时,将调用超类静态方法。

所以

public class SuperClass {
    public static void write() {
        System.out.println("Writing Super");
    }
    public void writeMore() {
        System.out.println("super something");
    }
}
public class SubClass extends SuperClass {
    public static void write() {
        System.out.println("Writing Sub");
    }
    public void writeMore() {
        System.out.println("sub something");
    }
}
public class Test {
    public static void main(String[] args) {
        SuperClass super = new SubClass();
        super.write();
        super.writeMore();
    }
}

将输出

Writing super
sub something

如果要从子类调用静态 write() 方法。您必须从子类中引用它。例如:

SubClass sub = new Subclass();
sub.write();

我了解到这一点的一些来源: https ://www.geeksforgeeks.org/can-we-overload-or-override-static-methods-in-java/ 为什么Java不允许覆盖静态方法?

于 2018-01-30T09:26:49.797 回答