关于java:为什么在覆盖该方法时调用超类方法?

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

本问题已经有最佳答案,请猛点这里访问。

从这些OCA实践问题(pdf)中的问题3开始:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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成员绑定到类而不是实例。因此,无论实例是什么,它们都会查看被调用和执行的类型。


如我们所知,不能重写static方法。如果我们尝试这样做,结果是方法隐藏。在上述情况下,Writer类和Programmer类都包含write()方法。

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

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


引用的类型是Writer。您调用了一个不应用重写的静态方法-将调用来自Writer的方法。

这种机制称为方法隐藏。

查看这些案例:

1
2
3
4
5
6
7
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中没有重写静态方法的事情。这就是为什么从超类引用调用静态方法时,将调用超类静态方法。

所以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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();
    }
}

意志输出

1
2
Writing super
sub something

如果要从子类调用static write()方法。你必须从一个子类中引用它。例如。:

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

我了解到的一些信息来源:https://www.geeksforgeks.org/can-we-overload-or-override-static-methods-in-java/为什么Java不允许重写静态方法?