我有一个C类。E类对此进行了扩展。

E e = new E();
C c = new C();

为什么是
e = (E) c;

经过进一步审查:尽管数字转换的语法与转换对象的语法相同,但仍引起一些混淆。无论如何,上面的代码没有给出编译结果,而是给出了运行时错误-因此,在某些情况下,可以将类强制转换为子类(否则,代码将无法编译)。任何人都可以给出上述工作原理的例子吗?

并且:
K extends M

K k = new K();
((M) k).getClass()给出K。这是为什么?它被强制转换为更通用的M!

假设我在M和K中都实现了doIt()方法。
((M) k).doIt();

给M或K的doIt()?

谢谢!

最佳答案

考虑一个真实的例子:

public class Dog extends Animal

所有的狗都是动物,但并非所有的动物都是狗。因此...
public class Cat extends Animal

仅在相关动物确实是狗的情况下,才能将动物丢给狗。否则,它将迫使宇宙将狗特有的属性(摇摆的尾部,吠叫等)推断到动物上。该动物很可能是具有其独特属性(发出刺耳声,严格的自我清洁机制等)的猫。如果无法进行强制转换,则在运行时引发ClassCastException。

没有人想要一只狗发出呼pur声。



您已将k强制转换为M,但是所有类都有一个getClass()方法。 k的类始终为K,无论您对它的引用是否为M。如果您将狗扔给动物,然后问它是什么动物,它仍然会回答它是狗。

实际上,强制转换为父类(super class)是多余的。狗已经是动物,它拥有动物的所有方法以及它自己的方法。许多代码分析工具(例如FindBugs)会通知您多余的转换,因此您可以将其删除。



K的doIt()的原因与上述相同。强制转换在引用上进行;它不会将对象转换为其他类型。



当然可以。想象一下一种方法,该方法接收要处理的动物列表。所有的狗都需要散步,所有的猫都需要使用鸟形玩具来玩耍。为此,我们调用仅在Dog上存在的takeForWalk()方法,或仅在Cat上存在的play()方法。
public void amuseAnimals( List<Animal> animals ) {
    for ( Animal animal : animals ) {
         if ( animal instanceof Dog ) {
             Dog doggy = (Dog)animal;
             doggy.takeForWalk( new WalkingRoute() );
         } else if ( animal instanceof Cat ) {
             Cat puss = (Cat)animal;
             puss.play( new BirdShapedToy() );
         }
     }
}

关于java - 有关Java多态性和强制转换的问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1082453/

10-11 15:18
查看更多