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

关于Java多态性和转换的问题,java,casting,polymorphism,Java,Casting,Polymorphism,我有一个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 假设

我有一个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

假设我有一个doIt()方法同时在M和K中实现

((M) k).doIt();
给出M或K的doIt()


谢谢

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

编辑:在下面展开Mark的评论。。。只是因为每个女人都是人,不是所有的人都是女人。所有人的腿、手、脸等都共享“人机界面”。当你提供钻石和黄金时,女性会通过返回美好感觉的功能来扩展它

int=>double转换甚至不相关,因为它不是一个类强制转换,而是一个告诉编译器将x中的内容存储在y中的转换(碰巧是double)

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

因为k仍然是一个k,即使你把它投射到一个M或者一个对象(或者它碰巧是的其他东西)

<>强>编辑:< /强>我认为这里的混乱是因为你认为K在你做它的时候变成“M”,而不是。你只是把它当作M。
如果你问一个“狗主人”是什么品种的狗,他不会返回“it's a dog”,原因很简单,getBreedName()方法很可能在子类LabradorOwner中被重写,返回“Labrador”。与getClass()相同,它将返回实现的类。它不是一个M,而是一个恰好也是M的K,因为K扩展了M。

int
/
double
是不相关的;这是一种转换,而不是强制转换-在
int
double
之间没有关系

重新考虑这个问题;类型的对象在创建时是固定的。作为
C
对象不是(也永远不可能)是
E
。但是,您可以将
E
视为
C
,因为继承表示“是”。例如:

E e = new E();
C c = e;
在这里,我们仍然只有一个对象,
c
变量将其视为
c
,因此不会公开特定于
E
的方法(即使对象
E

如果我们再加上:

E secondE = (E) c;
这是一种类型检查;同样,我们没有更改对象,但是将
c
放入
E
变量需要我们向编译器/运行时证明它确实是
E
。在第一个例子中我们不需要这个,因为它已经可以证明任何
E
也是
C

同样,对于
getClass()
,cast所做的只是改变编译器对对象的看法;您尚未更改对象本身。它仍然是一个
K


您需要将变量与对象分开。演员们正在谈论变数;它们不会更改对象。

对于第一个问题,您不能将超类强制转换为子类,因为子类添加了超类没有的成员。编译器在进行强制转换时,如何知道要将哪些值放在那里?基本上,E是C,但C不是E


getClass()获取内存中对象的类型。转换为M只是隐藏了一个事实,即它是一个K,它不会改变底层对象。

在Java中不能转换对象

您可以在Java中强制转换引用

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


转换基元值与转换引用不同。在这种情况下,值确实会发生变化。

要添加到Frederik的答案中,将对象强制转换到某个对象不会改变其类型。此外,对象只能强制转换为它已经是的类型(编译器当时不知道) 这就是为什么不可能的演员阵容永远不会被接受的原因:

Integer i = (Integer) new String();

不会编译,因为编译器知道这是不可能的。

请考虑一个实际示例:

public class Dog extends Animal
所有的狗都是动物,但不是所有的动物都是狗。因此

public class Cat extends Animal
只有在所讨论的动物确实是狗的情况下,才能将动物扔给狗。否则,它将迫使宇宙推断出狗对动物特有的属性(摇尾巴、吠叫等)。那只动物很可能是一只猫,有它特有的特性(咕噜咕噜,严格的自我清洁制度,等等)。如果无法执行强制转换,则在运行时抛出ClassCastException

没有人想要一只会咕噜咕噜的狗


((M)k).getClass()给出了k.为什么?它是铸造给更一般的M

您已经将k转换为M,但所有类都有一个getClass()方法。k的类始终是k,不管您是否将其引用转换为M。如果你把一只狗扔给一只动物,问它是什么动物,它仍然会回答是狗

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


假设我有一个doIt()方法同时在M和K中实现

((M) k).doIt();
(M)k.doIt()

给出M或K的doIt()

K的doIt()的原因与上面相同。cast根据参考进行操作;它不会将对象转换为其他类型


你能举个例子说明什么时候施放(Dog doggy=(Dog)myAnimal)有意义吗

当然可以。想象一个接收数据的方法
E e = new C();
e.myName();
E e = new E();
C c = (C)e;