class Animal{
public void findAnimal(){
System.out.println("Animal class");
}
public void sayBye(){
System.out.println("Good bye");
}
}
class Dog extends Animal{
public void findAnimal(){
System.out.println("Dog class");
}
}
鉴于上面的继承,可以理解 Animal 的引用可以引用 Dog 的对象
Animal animal=new Dog();
由于 Dog 对象可以执行 Animal 可以执行的所有操作,就像在上述情况中一样,Dog 也有 sayBye 和 findAnimal 方法。
但是为什么允许将 Animal 对象向下转换为 Dog 对象,这没有任何用处并且在运行时会失败。
Dog dog=(Dog)new Animal(); // fails at runtime but complies.
Dog dog=(Dog)animal;
上面的语句看起来合乎逻辑,因为动物引用指向 Dog 对象。
最佳答案
当您从外部代码获取父类(super class)的对象时,这种类型的转换是允许的,例如作为方法的参数,然后您需要调用特定于子类的方法。
这不是一个好的做法,但在一些罕见的情况下你被迫做这样的事情,所以语言允许这样做:
void sound(Animal animal) {
if (animal instanceof Dog) {
Dog dog = (Dog)animal();
dog.bark();
}
if (animal instanceof Cat) {
Cat cat = (Cat)animal();
cat.meow();
}
}
why it is allowed to compile
Dog dog=(Dog) new Animal()
因为编译器设计者决定在编译时不检测这个错误。他们验证了被转换为 Dog
的表达式的类型是 Dog
的父类(super class),并允许表达式编译。他们可以更进一步,检查表达式是否始终会导致异常,但这需要额外的努力,对使用该语言的用户体验的改进微乎其微。
关于java - 为什么在java中允许向下转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30659789/