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

的实例我将尝试通过以下步骤进行解释:

  • Reference
    ref1
    指向类
    C
    的实例
  • Reference
    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的变量一起使用,我已经更新了我的答案,并做了进一步的解释。