java - 向上转换对象时,哪些部分引用父对象,哪些部分引用子对象?
问题描述
在下面的示例中,我很困惑为什么向上转换似乎是指父类的某些部分和实际类的某些部分。
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 编译器使用引用类型将名称解析为类成员。因为((A)b)
有类型A
:
((A)b).fi
指fi
A中的变量。((A)b).getNum()
指getNum
A 中的方法。例如,您可以通过在声明中添加已检查异常A.getNum()
,同时将异常排除在B.getNum()
. 编译器将要求您捕获或声明((A)b).getNum()
可能抛出的异常,同时它允许您在b.getNum()
不进行此类更改的情况下调用。
另一方面,Java 具有方法的动态分派。动态分派意味着在运行时,JVM 查看实际对象的类型是什么。如果对象覆盖了您正在调用的方法,则 JVM 会改为调用覆盖。这表示:
((A)b).getNum()
将在运行时调用 B 中定义的方法。
推荐阅读
- javascript - Javascript - 所有数组都是文字吗?
- c# - Moq - 调用原始方法实现但更改输入参数之一
- javascript - 如何在页面第一部分隐藏元素
- c# - “/”应用程序中的 System.Resources.MissingManifestResourceException 服务器错误
- python - Python 中的 Strip 方法并不能全部清除
- session - Internet Explorer 等待用户操作 - 后台不刷新
- python - 在 tk.Entry 中显示灰色的默认文本
- angular - 在打字稿中使生命周期钩子异步(Angular,Ionic)
- python - 如何将代码编程为运行特定时间并在此之后退出?
- java - 检测点击了哪个按钮