假设我有三个班级A,B和C。
C延伸B,而B延伸A。 一个实现接口InterfaceA B实现接口InterfaceB1和InterfaceB2。
找到所有可能的向下转换组合的最佳方法是什么?
我的意思是?
假设我们有: B b =新的B(); InterfaceA i =(InterfaceA)(A)(B)b。
我们如何才能容易地知道它是否可以编译以及是否会在没有IDE的情况下导致classcastException?
我知道对象和引用是如何工作的,并且对Java中的多态性有相当的了解。
我开始绘制类和接口结构的草图。
编辑:我知道我的例子是不正确的,但是当界面加入故事时,我总是很努力。
答案 0 :(得分:0)
让我们首先处理“是否编译”。
确定这一点的关键是查看编译时类型,即变量的声明类型。
通常
要确定转换是否在运行时成功,关键是查看存储在变量中的对象的运行时类型。例如:
A a = new B();
a
的编译时间类型为A
,而运行时类型为B
。
通常,只有在T
继承自U
或实现T
的情况下,从运行时类类型U
转换为类或接口类型U
才能成功。 / p>
对于未来的读者,
如果您想知道如何使用代码检查强制转换是否成功,则应参考此question。
答案 1 :(得分:0)
首先,在您的方案中,以下内容完全不是向下转换,因为在所描述的层次结构中B是B,B是A并且B是InterfaceA。因此,所有这些强制转换都可以省略。
InterfaceA i = (InterfaceA)(A)(B) b;
然后,回答您的问题。只有在运行时可能成功时,向下转换才可以编译。让我们介绍其他的类D,它扩展了类A并实现了InterfaceB1。
A a = new A();
InterfaceB1 b1 = (InterfaceB1) a; // compilable as A reference can contain object of class B that implements InterfaceB1
InterfaceB2 b2 = (InterfaceB2) a; // compilable as A reference can contain object of class B that implements InterfaceB2
b1 = (InterfaceB1) b2; // compilable as InterfaceB2 reference can contain object of class B that implements both InterfaceB1, InterfaceB2
B b = (B) a; // compilable as A reference can contain object of class B
C c = (C) a; // compilable as A reference can contain object of class C
D d = (D) a; // compilable as A reference can contain object of class D
d = (D) b1; // compilable as InterfaceB1 reference can contain object of class D in runtime
b = (B) d; // not compilable since D reference can NEVER contain object of class B in runtime
c = (C) d; // not compilable since D reference can NEVER contain object of class D in runtime
对于导致ClassCastException的问题,始终与对象引用中实际包含的内容有关。
A a1 = new A();
A a2 = new B();
InterfaceB1 b1 = (InterfaceB1) a1; // compiles but causes ClassCastException as A cannot be cast to InterfaceB1
InterfaceB1 b2 = (InterfaceB1) a2; // compiles and runs just normally as B can be cast to InterfaceB1