不明确的java层次结构

我的问题是为什么下面的x.proc(z)打印57而不是打印39?

 class X { protected int v=0; public X() {v+=10; System.out.println("constr X");} public void proc(X p) {System.out.println(43);} } class Y extends X { public Y() {v+=5;System.out.println("constr Y");} public void proc(X p) {System.out.println(57);} public int getV() {return v;} } class Z extends Y { public Z() {v+=9;System.out.println("constr Z");} public void proc(Z p) {System.out.println(39);} } class Main { public static void main(String argv[]) { X x = new Z(); // v=24 Y y = new Z(); // v=24 Z z = new Z(); // v=24 x.proc(z); //57 } } 

X x指的是Z对象, Z类的确有方法proc(Z p)但它也有方法proc(X p) 。 参数z也是Z型,因此打印39是合理的。

方法

 public void proc(Z p) {System.out.println(39);} 

Z中不会覆盖

 public void proc(X p) {System.out.println(43);} 

X因为它将域限制为Z而不是X

但是, Y 的类比方法确实覆盖了X proc

由于x的编译时类型是X ,因此匹配x.proc(z)的唯一方法签名是public void proc(X p) 。 只有现在才进行动态调度,并且选择并执行来自Y的覆盖版本,这导致输出“57”,如预期的那样。

首先,编译器首先选择在编译时调用哪个方法(带签名)。 通过方法解析要调用的签名,考虑变量的编译时类型; 多态在这里不适用。 x的编译时类型是X ,即使它在运行时确实是Z对象。 只考虑proc(X) ,并且匹配,因为你传入的zX

在运行时,Java中的多态性意味着要考虑调用该方法的对象的运行时,以确定要调用哪个覆盖。 Y的过程优先于X的过程。 但是, Zproc方法采用Z而不是X ,所以Zproc方法重载 proc ; 它不会覆盖它。 因此,选择Y的过程。

因为你没有覆盖 proc方法,但是你正在重载它 – 这意味着你正在创建另一个具有相同名称但不同参数列表的方法。

将使用最合适的方法。