为了账号安全,请及时绑定邮箱和手机立即绑定

从超类到子类的显式转换

从超类到子类的显式转换

慕田峪7331174 2019-07-30 11:02:24
从超类到子类的显式转换public class Animal {     public void eat() {}}public class Dog extends Animal {     public void eat() {}     public void main(String[] args) {         Animal animal = new Animal();         Dog dog = (Dog) animal;     }}赋值Dog dog = (Dog) animal;不会生成编译错误,但在运行时会生成一个ClassCastException。为什么编译器无法检测到此错误?
查看完整描述

3 回答

?
DIEA

TA贡献1820条经验 获得超2个赞

通过使用演员你基本上告诉编译器“相信我。我是一个专业人士,我知道我在做什么,我知道虽然你不能保证,我告诉你这个animal变量肯定是要成为一只狗。“

由于动物实际上不是一只狗(它是一种动物,你可以这么做Animal animal = new Dog();,它可能是一只狗)VM在运行时抛出异常,因为你违反了那种信任(你告诉编译器一切都会好的,而且它是不!)

如果你尝试在不同的继承层次结构中强制转换对象(例如将一个Dog转换为一个String),那么编译器会比盲目地接受所有内容更聪明一点,然后编译器会将它抛回给你,因为它知道它永远不会起作用。

因为你基本上只是停止编译器的抱怨,所以每次你强制转换它都很重要,以确保你不会在if语句中ClassCastException使用by instanceof(或者那种效果)。


查看完整回答
反对 回复 2019-07-30
?
皈依舞

TA贡献1851条经验 获得超3个赞

因为理论上Animal animal 可以是一只狗:

Animal animal = new Dog();

一般来说,向下转型不是一个好主意。你应该避免它。如果您使用它,最好包括一个支票:

if (animal instanceof Dog) {
    Dog dog = (Dog) animal;}


查看完整回答
反对 回复 2019-07-30
?
米脂

TA贡献1836条经验 获得超3个赞

为了避免这种ClassCastException,如果你有:

class Aclass B extends A

你可以在B中定义一个带有A对象的构造函数。这样我们可以做“强制转换”,例如:

public B(A a) {
    super(a.arg1, a.arg2); //arg1 and arg2 must be, at least, protected in class A
    // If B class has more attributes, then you would initilize them here}


查看完整回答
反对 回复 2019-07-30
  • 3 回答
  • 0 关注
  • 367 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号