为什么叫"method hiding"?

Why is it called "method hiding"?

来自docs、"If a subclass defines a static method with the same signature as a static method in the superclass, then the method in the subclass hides the one in the superclass."

我了解方法隐藏和覆盖之间的区别。但是,说子类隐藏了超类的方法就很奇怪了,因为如果你有以下情况:

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Cat");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Cat");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;
        Animal.testClassMethod();
        myAnimal.testInstanceMethod();
    }
}

调用了超类的静态方法。但是根据隐藏的定义,子类中的方法隐藏了超类中的方法。我看不出子类是如何 "covering up/hiding" 超类静态方法的,因为超类的方法是实际调用的方法。

CattestClassMethod() 隐藏了 Animal.testClassMethod(),因为如果 Cat class 中没有静态 testClassMethod() , Cat.testClassMethod() 会调用 Animal.testClassMethod().

当你调用Animal.testClassMethod()时,它不能被子class的方法隐藏。

The superclass's static method is called.

是的。但那是因为您通过在调用语句中使用超类名称限定来显式命名超类的静态方法。

如果您是这样写 main 的:

public static void main(String[] args) {
    ...
    testClassMethod();
}

那么您会看到调用了 testClassMethodCat 版本。这里,Cat.testClassMethod方法隐藏了Animal.testClassMethod方法

考虑将此添加到您发布的示例中

class Dog extends Animal {
    // nothing here
}

现在如果你这样做:

new Cat().testClassMethod();
new Dog().testClassMethod();

以上每个都会给出不同的输出。所以你可以说 Cat 中的静态方法确实隐藏了 Animal 的静态方法 - 虽然没有覆盖静态方法这样的东西,但根据 Animal 打印的动物之一的代码而另一个没有。

(P.S。我绝对不鼓励你用这种方式调用静态方法。)

我认为它被称为"hiding",因为您不能再仅通过写方法名来访问超类的方法。没有 Cat 中的 public static void testClassMethod() 定义,您的 main 可以说

testClassMethod();

调用Animal中定义的方法。但是你不能再那样做了。是的,您仍然可以通过给它指定限定名称来调用它:

Animal.testClassMethod();

所以它没有完全隐藏。但请注意,编写语言标准的人必须为一些概念命名,这些概念可能与我们在非计算世界中赋予单词的含义不太相符,因此有时接近是他们能做的最好的事情。您不能尝试从字面上理解这些术语。我相信 hidden 这个词在 JLS 的某处有一个正式的定义;这意味着当您看到 JLS 中使用的术语时,它表示 JLS 定义的任何含义,不多也不少。