从超类到子类的显式转换

新手上路,请多包涵
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 。为什么编译器不能检测到这个错误?

原文由 saravanan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 522
2 个回答

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

由于动物实际上不是狗(它是动物,你可以做 Animal animal = new Dog(); 它是一只狗)虚拟机在运行时抛出异常,因为你违反了这种信任(你告诉编译器一切都会好起来的,但事实并非如此!)

编译器比盲目接受一切更聪明,如果你尝试在不同的继承层次结构中转换对象(例如将 Dog 转换为 String),那么编译器会把它扔回给你,因为它知道这永远不可能工作。

因为你基本上只是阻止编译器抱怨,所以每次你强制转换时,重要的是检查你不会导致 ClassCastException 通过在 if 语句(或其他东西)中使用 instanceof 达到那个效果。)

原文由 Michael Berry 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

 Animal animal = new Dog();

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

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

原文由 Bozho 发布,翻译遵循 CC BY-SA 2.5 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题