我有以下2个课程:
class Animal {
public static void staticMethod(int i) {
System.out.println("Animal : static -- " + i);
}
public void instanceMethod(int i) {
System.out.println("Animal : instance -- " + i);
}
}
class Cat extends Animal {
public static void staticMethod(int i) {
System.out.println("Cat : static -- " + i);
}
public void instanceMethod(int i) {
System.out.println("Cat : instance -- " + i);
}
public static void main(String[] args) {
Cat myCat = new Cat();
myCat.staticMethod(1); // Cat : static -- 1
myCat.instanceMethod(2); // Cat : instance -- 2
System.out.println("");
Animal myAnimal = myCat;
Animal.staticMethod(3); // Animal : static -- 3
myAnimal.staticMethod(4); // Animal : static -- 4 [ ? ]
System.out.println("");
myAnimal.instanceMethod(5); // Cat : instance -- 5
}
}
当我运行Cat时,得到以下结果:
Cat : static -- 1
Cat : instance -- 2
Animal : static -- 3
Animal : static -- 4
Cat : instance -- 5
我可以理解1,2,3和5,但是为什么#4不是:“Cat:静态-4”?
我的理解是这样的:
myAnimal = myCat表示“myAnimal”现在与“myCat”完全相同,因此在任何“myAnimal”豌豆中,您都可以将其替换为“myCat”,并获得相同的结果,因为myAnimal中的所有内容都与myCat中的所有内容相同,因此,“myAnimal.staticMethod(4)”应与“myCat.staticMethod(4)”相同,输出应为:“Cat:static-4”,与上述“myCat.staticMethod(1)”类似。
但是,事实并非如此,为什么?
最佳答案
从Oracle docs:
8.4.8.2。隐藏(按类方法)
如果类C声明或继承了静态方法m,则称m为
隐藏任何方法m',其中m的签名是子签名
的超类中m'的签名(第8.4.2节)
C的超级接口,否则C中的代码将可以访问它们。
示例8.4.8.2-1。调用隐藏类方法
隐藏的类(静态)方法可以使用
类型为实际上包含以下内容的类的引用
方法的声明。在这方面,隐藏静态方法
与重写实例方法不同。这个例子:
class Super {
static String greeting() { return "Goodnight"; }
String name() { return "Richard"; }
}
class Sub extends Super {
static String greeting() { return "Hello"; }
String name() { return "Dick"; }
}
class Test {
public static void main(String[] args) {
Super s = new Sub();
System.out.println(s.greeting() + ", " + s.name());
}
}
产生输出:
晚安,迪克
因为Greeting的调用使用s的类型,即Super,
在编译时找出要调用的类方法,而
名称的调用使用s的类(即Sub)来确定,
在运行时,调用哪个实例方法。