将超类强制转换为子类

时间:2013-01-22 21:06:43

标签: java class object inheritance casting

想象一下 Cottage扩展建筑和代码

Building building = new Building();
Cottage cottage = (Cottage)building;

现在,考虑到java继承的本质,构建无法转换为 Cottage 是完全有道理的,但对我来说没有意义(对我而言)是这个编译。为什么要编译然后抛出运行时 ClassCastException

在实际运行程序之前,构建是否是对构建对象的引用并不明显?

这是一个普遍的问题,我知道我得到了一个可能的副本:)但是我找不到为什么要编译问题的答案:)

EDIT2 我在这里接受了一个很好的答案(更不用说下面的讨论:)),但我仍然在Java casting resulting in run-time error instead of compilation error中找到最有趣的答案......

编辑我修改了 IllegalCastException 并输入了正确的 ClassCastException

3 个答案:

答案 0 :(得分:10)

那是因为编译器不知道你的引用Building指的是什么对象。

所以,在下面的例子中,你有一个基类引用,指向子类对象: -

Building building = new Cottage();
Cottage cottage = (Cottage)building;

它会完美无缺。因此,它完全是一个运行时决定,关于它是否是有效的强制转换。因此,编译器不会为此抛出错误。

  

构建是对Building对象的引用是不是很明显   在实际运行程序之前?

不。绝对不是。被引用的对象类型直到运行时才知道。永远记住,编译器始终检查引用类型。在运行时检查实际对象类型。

这个概念被称为 Polymorphism ,您可以使用相同的引用类型指向各种子类型的对象。你可以谷歌它,并将获得大量的资源来阅读。

答案 1 :(得分:3)

强制转换的部分功能是让编译器闭嘴,你说你比编译器更了解你所投射的对象是什么。如果演员阵容不准确,你将获得例外。

也许您期望编译器跟踪事物所指向的对象,并且如果引用是合理的则可以计算出来。编译器并不聪明,很容易被愚弄,请看这个片段:

    int i = 1;
    System.out.println((Number)i);        
    Object o = i;
    System.out.println((String)i); // won't compile (primitive-to-ref-type cast)
    System.out.println((String)o); // compiles (thanks to autoboxing)

编译器只关心阻止基元和引用类型之间的转换。

答案 2 :(得分:2)

考虑使用Building(超类)引用

创建一个Cottage(Subclass)对象
Building b= new Cottage();
Cottage c = (Cottage) b;

上面的代码是合法的,因此编译器不会知道引用变量c在运行时引用了什么对象,因此编译器不会抛出错误。

  

为什么要编译然后抛出运行时IllegalCastException?

顺便说一下,当你尝试将超类对象强制转换为子类时,它会抛出 ClassCastException ,而不是 IllegalCastException