为什么在覆盖该方法时调用超类方法? (来自OCA练习测试)

Why is superclass method called while that method is overriden? (from OCA practice test)

来自these OCA practice questions (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...

我不明白为什么。由于 Programmer 覆盖了 Writer 的 write 方法,我认为它应该调用 Programmer 中的方法而不是 Writer 中的方法。

为什么?

这里你要明白两点。

如果有 static 个成员,则没有压倒一切的概念。它们只是 static 并且永远不会根据实例改变。

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

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

该机制称为 method hiding


查看这些案例:

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

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

new Writer() {{}}.write();            // ...   [Writer]

自己找到了答案。

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/ Why doesn't Java allow overriding of static methods?

众所周知,static 方法不能被覆盖。如果我们尝试这样做,结果却是方法隐藏。在上面的例子中,class- WriterProgrammer 都包含 write() 方法。

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

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