如何查看Java转换是否合法?

时间:2019-01-20 12:46:32

标签: java inheritance casting

假设我有三个班级A,B和C。

C延伸B,而B延伸A。 一个实现接口InterfaceA B实现接口InterfaceB1和InterfaceB2。

找到所有可能的向下转换组合的最佳方法是什么?

我的意思是?

假设我们有: B b =新的B(); InterfaceA i =(InterfaceA)(A)(B)b。

我们如何才能容易地知道它是否可以编译以及是否会在没有IDE的情况下导致classcastException?

我知道对象和引用是如何工作的,并且对Java中的多态性有相当的了解。

我开始绘制类和接口结构的草图。

编辑:我知道我的例子是不正确的,但是当界面加入故事时,我总是很努力。

2 个答案:

答案 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