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使用instanceof(或类似的东西)。
instanceof