Java OCJP多态流
大家好, 我非常惊讶地看到以下程序的输出:Java OCJP多态流,java,polymorphism,overriding,Java,Polymorphism,Overriding,大家好, 我非常惊讶地看到以下程序的输出: class A{ int f() {return 0;} int g() {return 3;} } class B extends A{ int f() {return 1;} int g() {return f();} } class C extends B { int f() {return 2;} } public class Test { public static void main(String args[]){ A ref1
class A{
int f() {return 0;}
int g() {return 3;}
}
class B extends A{
int f() {return 1;}
int g() {return f();}
}
class C extends B {
int f() {return 2;}
}
public class Test {
public static void main(String args[]){
A ref1 = new C();
B ref2 = (B)ref1;
System.out.println(ref2.g());
}
}
请帮助我解释代码。您正在创建
C
的实例,并使用A
类型将其分配给ref1
。此外,您正在声明类型为B
的变量ref2
,该变量被赋值为ref1
。ref1
的值仍然是C
的一个实例,即使您按类A
查看它
调用ref2.g()
在变量ref2
的实例上执行方法g()
。这仍然是唯一创建的C
实例。通过类B
的类型查看它不会改变变量ref2
所指实例的实现
让我们通过方法inth(){return 5;}
扩展类C
。使用ref2
无法调用方法h()
,因为变量的类型是B
。但是h()
仍然存在于引用的实例ref2
上。如果扩展main方法
C ref3 = (C) ref2;
System.out.println(ref3.h());
这将输出5
。但是将ref2
的值赋给ref3
并调用它h()
意味着ref2
和ref3
(和ref1
)的值是相同的
System.out.println(ref2 == ref3);
这将输出
true
。因此,两个变量都指向同一个对象,C
的实例我将尝试通过以下步骤进行解释:
ref1
指向类C
的实例ref2
指向类C
的同一实例。不管它是用显式类型转换完成的,堆中的实例仍然具有类型C
。再一次:
的类型为ref2
李>B
- 指向
的对象实例的类型为ref2
C
ref2.g()
时,JVM实际上试图在类C
中找到方法g()
(因为堆中的对象实例具有类型C
,如上所述)。因为类C
中没有方法g()
,JVM移动到父类B
,在其中找到方法g()
,并调用它B
中调用方法g()
将导致方法f()
。JVM再次尝试最初在类C
中查找该方法,找到它并返回值2
此代码表示重写。在运行时重写时,jvm决定调用哪个方法(也称为后期绑定)
现在来看代码,
类C
有一个被重写的方法f()
,在您键入的代码中,将类A(ref1
)的引用铸造到类B,并调用g()
方法,因此在运行时jvm将调用g()类B的方法和ref2
是类B的引用,它指向类C
对象,因此在运行时C类的f()
方法已绑定,它将调用C类的f()
方法 输出是什么,您不了解什么?输出是:2,但为什么不打印1?正如我们所知,本地成员总是获得优先权,那么为什么不从return语句中调用B的f()方法。因为ref2
属于B
类型,如果它没有被C
覆盖,它的方法f
将被调用。但是它被类型C
覆盖,变量ref2
的实例被引用为类型C
,即使您将其与类型B
@Tavash的变量一起使用,我已经更新了我的答案,并做了进一步的解释。