从文档中,"如果一个子类定义了一个静态方法,该方法与超类中的静态方法具有相同的签名,那么子类中的方法会隐藏超类中。"
我理解方法隐藏和重写之间的区别。然而,说子类隐藏了超类方法是很奇怪的,因为如果你有以下内容:
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();
}
}
调用了超类的静态方法。但是根据隐藏的定义,子类中的方法就是隐藏超类中的那个方法。我看不出子类是如何"掩盖/隐藏"超类静态方法的,因为超类的方法就是实际调用的方法。
调用了超类的静态方法。
是的。但这是因为您通过在调用语句中限定超类名称来显式命名超类的静态方法。
如果你把main
写成这样:
public static void main(String[] args) {
...
testClassMethod();
}
那么您会看到调用了testClassMethod
的Cat
版本。这里,Cat.testClassMethod
方法隐藏Animal.testClassMethod
方法
Cat
的testClassMethod()
隐藏Animal.testClassMethod()
,因为如果Cat
类中没有静态testClassMethod()
,Cat.testClassMethod()
将调用Animal.testClassMethod()
。
当您调用Animal.testClassMethod()
时,它不能被子类的方法隐藏。
我认为它被称为"隐藏",因为您不能再简单地通过编写方法名来访问超类的方法。如果没有Cat
中的public static void testClassMethod()
定义,您的main
可以说
testClassMethod();
以调用CCD_ 17中定义的方法。但你不能再那样做了。是的,你仍然可以给它一个合格的名字:
Animal.testClassMethod();
所以它不是完全隐藏的。但请注意,编写语言标准的人必须为一些概念命名,这些概念可能与我们在非计算世界中赋予的单词的含义不太匹配,所以有时接近是他们能做的最好的事情。你不能试图从字面上理解术语。我相信hidden
一词在JLS中有一个正式的定义;这意味着,当你看到JLS中使用的术语时,它意味着JLS定义的任何含义,既不多也不少。
考虑将其添加到您发布的示例中
class Dog extends Animal {
// nothing here
}
现在,如果你这样做:
new Cat().testClassMethod();
new Dog().testClassMethod();
以上每一个都将给出不同的输出。所以你可以说Cat
中的静态方法确实隐藏了Animal
的静态方法——虽然没有覆盖静态方法这回事,但其中一只动物是根据Animal
的代码打印的,另一只没有。
(附言:我绝对不鼓励你用这种方式调用静态方法。)