关于Java多态性和转换的问题

oob*_*boo 8 java polymorphism casting

我有一个班级C.班级E扩展了它.

E e = new E();
C c = new C();
Run Code Online (Sandbox Code Playgroud)

为什么是

e = (E) c;
Run Code Online (Sandbox Code Playgroud)

进一步审查:虽然数字转换与铸造对象具有相同的语法,但是出现了一些混淆.在任何情况下,上面都没有给出编译,而是给出了运行时错误 - 所以在某些实例中可以将类转换为子类(否则代码将无法编译).任何人都可以给出上述工作的例子吗?

并且:

K extends M

K k = new K();
Run Code Online (Sandbox Code Playgroud)

((M) k).getClass()K.这是为什么?这是更普遍的铸造M!

假设我在M和K中都执行了doIt()方法

((M) k).doIt();
Run Code Online (Sandbox Code Playgroud)

给出M或K的doIt()?

谢谢!

ban*_*ity 15

考虑一个现实世界的例子:

public class Dog extends Animal
Run Code Online (Sandbox Code Playgroud)

所有的狗都是动物,但不是所有的动物都是狗.因此...

public class Cat extends Animal
Run Code Online (Sandbox Code Playgroud)

只有当动物确实是狗时,才能将动物施放给狗.否则它会迫使宇宙推断出一只狗独有的属性(摇尾巴,吠叫等)到动物身上.动物可能是一只具有独特属性的猫(咕噜咕噜,严格的自我清洁等等).如果无法进行强制转换,则会在运行时抛出ClassCastException.

没有人想要一条咕噜咕噜的狗.


((M)k).getClass()给出K.为什么?它被铸造给更一般的M!

你已经将k转换为M,但所有类都有一个getClass()方法.k的等级总是K,无论你是否将其引用给M.如果你把一只狗交给一只动物并问它它是什么动物它仍会回答它是一只狗.

实际上,转换为超类是多余的.狗已经是动物,它拥有动物的所有方法以及它自己的方法.许多代码分析工具(如FindBugs)会通知您冗余的强制转换,以便您可以删除它们.


假设我在M和K中都执行了doIt()方法

((M)k).doIt();

给出M或K的doIt()?

K的doIt()与上述原因相同.演员在参考上运作; 它不会将对象转换为其他类型.


你能给出一个铸造时的例子(Dog doggy =(Dog)myAnimal)有意义吗?

当然可以.想象一下接收动物列表进行处理的方法.所有的狗都需要散步,所有的猫都需要使用鸟形玩具.为此,我们调用takeForWalk()仅存在于Dog上的play()方法,或仅存在于Cat上的方法.

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() );
         }
     }
}
Run Code Online (Sandbox Code Playgroud)


Joa*_*uer 8

您无法在Java中强制转换对象.

您可以使用Java转换引用.

转换引用不会改变它引用的对象的任何内容.它仅生成指向与初始引用相同的对象的不同类型的引用.

转换原始值与转换引用不同.在这种情况下,值发生变化.


Fre*_*rik 7

仅仅因为E扩展了C,C不会成为E ......另一方面,E是C

编辑:扩展马克在下面的评论......仅仅因为每个女人都是人,而不是所有人都是女人.所有人都与腿,手,脸等共享"人机界面".当你提供钻石和黄金时,女性可以通过功能延伸到良好的感觉.

int => double转换甚至不相关,因为它不是类转换,而是转换告诉编译器存储y中的x中的任何内容(恰好是double).

((M)k).getClass()给出K.

因为k仍然是K,即使你把它投射到M或一个对象(或恰好是其他东西).

编辑:我认为这里的混乱是因为你认为k在你投射时"成为"M,它不会.你只是将它视为一个M.如果你问一个人是"狗主人"什么样的品种,他将不会返回"它是一只狗",原因很简单,getBreedName()方法很可能有已在子类LabradorOwner中重写以返回"Labrador".它与getClass()相同,它将返回实现的类.它不会是M而是K也恰好是M,因为K扩展了M.

  • 你不妨问:每个女人都是一个人; 为什么我不能把每个人当作女人对待?答:你**可以** - 但首先你需要*检查*他们是女人. (6认同)
  • 每个E都是C,但不是每个C都是E. E扩展C就像是说E添加到C因此C可能没有与E相同的数量. (2认同)