向上转型对象时,哪些部分引用父对象,哪些部分引用子对象?

When upcasting an object, what parts refer to the parent and what parts refer to the child?

在下面的示例中,我很困惑为什么向上转型似乎指的是父 class 的某些部分和实际 class 的某些部分。

public class B extends A{
   int fi = 15;
   public static void main(String[] args){
       B b = new B();
       b.fi = 20;
       System.out.println(b.fi);
       System.out.println(  (  (A) b  ).fi  );
       System.out.println(  (  (A) b  ).getNum());
   }
   public int getNum(){
       return fi;
   }
}
class A{
   final int fi = 5;
   public int getNum(){
       return fi * 2;
}

打印结果为:

20
5
20

我知道这段代码是以一些低效的方式编写的,但它类似于我得到的 OCA 练习题。我想知道为什么 ((A)b).fi 指的是 A 中的变量,而 ((A)b).getNum() 使用 B 中的变量和方法。如果向上转型指的是父级,应该'结果不是 20 5 10 吗?

这里有两种力量在起作用:

一方面,Java 编译器使用引用的 类型 将名称解析为 class 成员。因为 ((A)b) 的类型是 A:

  • ((A)b).fi指的是A中的变量fi.
  • ((A)b).getNum() 引用 A 中的方法 getNum。您可以通过例如向 [=16] 添加 checked exception 来查看事实=] 声明,同时将异常排除在 B.getNum() 之外。编译器将要求您捕获或声明 ((A)b).getNum() 可能抛出的异常,同时它允许您在不进行此类更改的情况下调用 b.getNum()

另一方面,Java 有 动态调度 方法。动态调度意味着在 运行 时间,JVM 会查看实际对象的类型。如果对象 覆盖 您正在调用的方法,则 JVM 会调用覆盖。这意味着:

  • ((A)b).getNum()会在运行时调用B中定义的方法。

方法选择了动态类型(B),属性选择了静态类型(A)。

也许其中一个链接可以帮助您: