在下面的例子中,我很困惑为什么upcasting似乎指的是父类的某些部分和实际类的一些部分。
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中的变量和方法。如果upcasting指的是父级,结果不应该是20 5 10
吗?
这里有两种力量在起作用:
一方面,Java编译器使用引用的类型来解析类成员的名称。因为((A)b)
具有类型A
:
((A)b).fi
是指A中的变量fi
((A)b).getNum()
指的是A中的方法getNum
。例如,您可以在A.getNum()
声明中添加检查的异常,同时将该异常排除在B.getNum()
之外。编译器将要求您捕获或声明((A)b).getNum()
可能引发的异常,而它允许您在不进行此类更改的情况下调用b.getNum()
另一方面,Java对方法有动态调度。动态调度意味着在运行时,JVM查看实际对象的类型。如果对象覆盖了您正在调用的方法,JVM将改为调用覆盖。这意味着:
((A)b).getNum()
将在运行时调用B中定义的方法
方法由动态类型(B(选择,但属性由静态类型(A(选择。
也许其中一个链接可以帮助你:
- 关于上行与动态绑定的混淆
- https://bruck.me/2014/01/08/java-statischer-vs-dynamischer-typ/->德语,但很好