It happens because you don't override the method 'proc' in Z class. When you overriding the method, you can't use argument, which has a child class of original argument class. If you add @Override on Z.proc(Z p), your code will be not compiled.
Let's imagine that it is possible, then you can use some method from Z class during executing Z.proc(Z p).
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");
}
}
Now when you executing
X x = new Z();
x.proc(new X());
What should happens? There is no 'someActions' method in the X class. How it should works? That's why Z.proc(Z p) doesn't override X.proc(X p). Class Z, has two different methods: Z.proc(Z p) and Y.proc(X p).
When you calling
X x = new Z();
x.proc(new Z());
JVM looks for closest overrided or original method with signature 'proc(X)' to Z class (because X class has 'proc(X)' method) finds it in Y class and executing Y.proc(x p). That's why you see '57' in output.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…