我有以下两门课:
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不是:“猫:静态-- 4”?我的理解是:
myAnimal=myCat的意思是" myAnimal“现在与" myCat”完全相同,所以在任何"myAnimal“词组中,您都可以用"myCat”替换它,得到相同的结果,因为myAnimal中的所有东西都与myCat中的所有东西相同,因此"myAnimal.staticMethod(4)“应该与"myCat.staticMethod(4)”相同,输出应该是:“猫:静态- 4",类似于上面的"myCat.staticMethod(1)”。
但情况似乎并非如此,为什么?
发布于 2015-04-28 21:10:14
来自Oracle文档
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());
}
}产生的输出: 晚安,迪克 因为问候语的调用使用s的类型,即Super,在编译时计算出要调用的类方法,而名称的调用使用s的类,即Sub,在运行时计算出要调用的实例方法。
发布于 2015-04-28 21:03:14
您可以声明myAnimal为Animal。因此,该类也调用了一个静态方法。
您不应该从实例中调用静态方法(或访问静态字段)来防止这种混乱。
发布于 2015-04-28 21:02:38
原因是Java基于引用变量本身的类型来解析静态方法,而不是像实例方法那样在运行时进行多态解析。
为了稍微扩展一下,在执行Animal myAnimal = myCat时,您要将一个猫引用分配给一个动物引用。这是可以接受的,因为Cat也是Animal,所以Animal可以做的任何事情,Cat也可以。
此外,如果您通过myAnimal引用调用一个实例(即非静态)方法,并且该方法在Cat中被覆盖,那么将调用该方法的Cat版本,因为这就是该方法首先被覆盖的原因。另一方面,静态方法永远不会被超越。这就是为什么它们是“静态”的,就像在“非动态”中一样。这意味着静态方法可以由编译器解析,而不必依赖运行时环境。
https://stackoverflow.com/questions/29929814
复制相似问题