OCJP多态流

时间:2018-08-24 05:59:55

标签: java polymorphism method-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 = new C();
    B ref2 = (B)ref1;
    System.out.println(ref2.g());
}
}

请帮助我解释代码。

3 个答案:

答案 0 :(得分:2)

您正在创建C的实例,并将其分配给ref1类型的A。此外,您还要声明类型为ref2的变量B,该变量将被赋值为ref1ref1的值仍然是C的实例,即使您正在按类A的类型查看

调用ref2.g()在变量g()的实例上执行方法ref2。这仍然是C的唯一实例。在类B查找不会改变变量ref2所引用实例的实现。

让我们通过方法C扩展类int h() { return 5; }。使用ref2不能调用方法h(),因为变量的类型是B。但是h()仍然存在于实例ref2上。如果您将主方法扩展为

C ref3 = (C) ref2;
System.out.println(ref3.h());

这将输出5。但是将ref2的值分配给ref3并调用h()意味着ref2ref3(和ref1)的值是一样。

System.out.println(ref2 == ref3);

这将输出true。因此,两个变量都指向同一个对象,即C的实例。

答案 1 :(得分:0)

我将尝试逐步解释:

  1. 引用ref1指向类C的实例。
  2. 引用ref2指向类C的相同实例。无论是通过显式类型转换完成的,堆中的实例仍然具有类型C。再次:
    • ref2的类型为B;
    • 指向ref2
    • 对象实例的类型为C
  3. 当我们调用ref2.g()时,JVM实际上尝试在类g()中查找方法C(因为如上所述,堆中的对象实例的类型为C) )。由于类g()中没有方法C,因此JVM移至父类B,在其中找到方法g(),然后调用它。
  4. 调用类g()中的方法B会导致方法f()。 JVM再次尝试在类C中最初找到该方法,然后找到它并返回值2

答案 2 :(得分:0)

此代码表示覆盖。并且在运行时重写时,jvm决定要调用的方法(也称为后期绑定)。

现在开始编写代码,class C具有重写的方法f(),并且在代码中,您已经键入了 A类ref1 )以 B类并调用g()方法,因此在运行时,jvm将调用g()的{​​{1}}方法,而class B是对ref2指向class B对象,因此在运行时class C的{​​{1}}方法已绑定,它将调用{{1}的f()方法}。