一尘不染

Java从父类到子类的显式转换

java

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。为什么编译器无法检测到此错误?


阅读 512

收藏
2020-03-09

共1个答案

一尘不染

通过使用强制转换,你实际上是在告诉编译器“相信我。我是专业人士,我知道我在做什么,我知道尽管不能保证,但是我告诉你这个animal变量肯定是会成为一只狗。”

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

编译器比盲目地接受所有内容要聪明一些,如果你尝试将对象强制转换为不同的继承层次结构(例如,将Dog投射到String),则编译器会将其扔给你,因为它知道这种方法永远无法工作。

因为你实际上只是在阻止编译器抱怨,所以每次转换时,都必须检查是否在if语句中ClassCastException使用不会引起a (这一点很重要instanceof)。

2020-03-09