[英]Why does the line marked with //1 print 57 instead of 39?
class X {
protected int v = 0;
public X() {
v += 10;
}
public void proc(X p) {
System.out.println(43);
}
}
class Y extends X {
public Y() {
v += 5;
}
public void proc(X p) {
System.out.println(57);
}
public int getV() {
return v;
}
}
class Z extends Y {
public Z() {
v += 9;
}
public void proc(Z p) {
System.out.println(39);
}
}
class Main {
public static void main(String[] args) {
X x = new Z();
Y y = new Z();
Z z = new Z();
x.proc(z);// 1
System.out.println(y.getV());
}
}
据我所知,proc() 方法在 X 类型的对象上被调用,该对象“持有”一个 Z 类型,并且在运行时 JVM 检查对象的类型并使用 Y 的 proc() 方法覆盖该方法。但是该方法参数是Z类型的,为什么不调用Z类的重载方法?
发生这种情况是因为您没有覆盖 Z 类中的方法 'proc'。 当您覆盖该方法时,您不能使用参数,它具有原始参数类的子类。 如果您在 Z.proc(Z p) 上添加 @Override,您的代码将不会被编译。
假设这是可能的,那么您可以在执行 Z.proc(Z p) 期间使用 Z 类中的某些方法。
class Z extends Y {
public Z() {
v += 9;
}
public void proc(Z p) {
someActions();
System.out.println(39);
}
private void someActions() {
System.out.println("Some actions");
}
}
现在当你执行
X x = new Z();
x.proc(new X());
应该发生什么? X 类中没有“someActions”方法。 它应该如何工作? 这就是为什么 Z.proc(Z p) 不会覆盖 X.proc(X p)。 Z 类有两种不同的方法:Z.proc(Z p) 和 Y.proc(X p)。
当你打电话
X x = new Z();
x.proc(new Z());
JVM 寻找与 Z 类(因为 X 类具有 'proc(X)' 方法)最接近的具有签名 'proc(X)' 的覆盖或原始方法,在 Y 类中找到它并执行 Y.proc(xp)。 这就是您在输出中看到“57”的原因。
因为您将X
传递给proc
,所以Y
类的proc
占上风。
如果你传递了一个实际的Z
声明为Z
,它会打印 39。
Z x = new Z();
X y = new Z();
Z z = new Z();
z.proc(x); // prints 39
z.proc(y); // prints 57
class X {
protected int v = 0;
public X() {
v += 10;
}
public void proc(X p) {
System.out.println(43);
}
}
class Y extends X {
public Y() {
v += 5;
}
public void proc(X p) {
System.out.println(57);
}
public int getV() {
return v;
}
}
class Z extends Y {
public Z() {
v += 9;
}
public void proc(Z p) {
System.out.println(39);
}
}
class Main {
public static void main(String[] args) {
X x = new Z();
Y y = new Z();
Z z = new Z();
x.proc(z);// 1
System.out.println(y.getV());
}
}
据我所知,proc() 方法被调用在一个 X 类型的对象上,该对象“持有”一个 Z 类型,并且在运行时 JVM 检查对象的类型并使用 Y 的 proc() 方法覆盖该方法。但是该方法参数是Z类型的,为什么不调用Z类的重载方法?
只是为了详细说明 Federico 的回答。 “x”对象实际上是一个“X”变量,指向内存中的“Z”实例。 "Z" 实例只有两种方法:
void proc(Z p)
void proc(X p)
但是运行时只知道在“X”类中实现的第二个方法,它被在“Y”类中实现的方法覆盖。 所以,当你打电话时:
x.proc(z)
运行时只知道第二个方法并调用它,执行覆盖的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.