1

谁能在这里向我解释为什么在将父级向下转换为子级时会出现 java.lang.ClassCastException?

public class Child extends Parent{
public static void main(String[] args){
    new Child().go();
}
void go(){
    go2(new Parent(), new Child());
    go2((Child) new Parent(), new Child());
}
void go2(Parent p1, Child c1){
    Child c2 = (Child)p1;
    Parent p2 = (Parent)c1;
} 
}
class Tree{}

我已阅读参考变量转换并在网络上搜索示例。有人可以向我解释一下吗?我真的很想了解它为什么会抛出异常。谢谢

4

6 回答 6

3

假设您是父类动物和子类鸟。你可以从鸟施法到动物,因为所有的鸟都是动物。你不能从动物施法到鸟,因为不是所有的动物都是鸟。

于 2013-05-09T09:25:16.530 回答
2

这是您有问题的代码剥离:

go2(new Parent());

...

void go2(Parent p1){
    Child c2 = (Child)p1;
}

编译器允许您将 p1 从“父”转换为“子”,因为 p1可能是“子”。但是,您可以清楚地看到, p1 不是孩子。所以你的代码在编译时很好,但在运行时会崩溃。

这意味着,您可能在“子”类中定义的所有添加行为都不可用,因为您只有一个“父”类型的实例。

于 2013-05-09T09:26:04.860 回答
1

您可以将 aChild转换为Parent. 由于Childextends Parent, a 的任何实例Child都是 a Parent(但额外的东西只对 a 可用Child)。然而,p1是一个Parent。由于 aParent 不是 a Child,因此您不能将 a 的实例强制Parent转换为 a Child

我从谷歌搜索中准确复制了类似问题的答案。下次请做好功课并阅读常见问题解答。

于 2013-05-09T09:25:28.923 回答
0

可以说Car是一个准系统界面

Merc is a Car (Merc extends Car)

BMW  is a Car (BMW extends Car)

现在

你可以把宝马当作汽车的所有功能一样对待它。所以你可以将 BMW 铸造到汽车上,这样(Car car = (Car)bmw) 是合法的。

如果你拿一辆准系统汽车并试图将其视为宝马,那是不可能的,因为宝马将拥有比准系统汽车多得多的东西。

所以,

BMW bmw = (BMW)car 是非法的

相同的现实世界概念扩展到面向对象的世界。

于 2013-05-09T09:31:49.707 回答
0

AParent不是Child. 也就是说, aParent确实具有必要的字段,可以将其视为一个实例Child并实现所有Child特定方法 - 的合同Child。想象一下,如果Child有一个变量childOnly和一个方法childProcess,并且您尝试调用内存中childProcess的一个对象。Parent它不可能工作,因此 Java 阻止您将父母视为孩子。

于 2013-05-09T09:25:51.913 回答
0

由于多态引用,当您存储sub-type要引用的对象时super-type,您不能使用特定于sub-type. 但你可以得到哪些是定义在super-type.

为了能够使用子类型方法,您需要转换 to 的super-type引用sub-type

Parent p = new Child();
...
...
((Child)p).childMethod();

但这只有在您知道分配给p的对象实际上是 type时才有可能Child。否则它会给ClassCastException

于 2013-05-09T09:28:07.073 回答