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。为什么编译器无法检测到此错误?
Dog dog = (Dog) animal
ClassCastException
通过使用强制转换,你实际上是在告诉编译器“相信我。我是专业人士,我知道我在做什么,我知道尽管不能保证,但是我告诉你这个animal变量肯定是会成为一只狗。”
animal
由于动物实际上不是狗(它是动物,你可以做Animal animal = new Dog();,也可能是狗),因此VM在运行时会引发异常,因为你违反了这种信任(你告诉编译器一切都会好的,并且不!)
Animal animal = new Dog()
编译器比盲目地接受所有内容要聪明一些,如果你尝试将对象强制转换为不同的继承层次结构(例如,将Dog投射到String),则编译器会将其扔给你,因为它知道这种方法永远无法工作。
因为你实际上只是在阻止编译器抱怨,所以每次转换时,都必须检查是否在if语句中ClassCastException使用不会引起a (这一点很重要instanceof)。
instanceof