我在java代码下面运行,我不明白为什么它返回0作为输出,而不是200或500。
class Bike{
int speedlimit;
}
class Honda3 extends Bike{
int speedlimit;
public static void main(String args[]){
Bike obj=new Bike();
obj.speedlimit=200;
Honda3 obj2=new Honda3();
obj2.speedlimit=500;
obj=obj2;
System.out.println(obj.speedlimit);
}
}
输出:0
我认为obj=obj2将像运行时多态性一样工作,但我的推理似乎不正确。不知道我在这里错过了什么。
我以前也没有使用过obj=obj2这样的代码,我在想是否有一个场景可以使用它?
4条答案
按热度按时间3vpjnl9f1#
创建对象时
Honda3
,创建的对象还包括父类的所有字段,即Bike
. 所有字段都用默认值初始化(speedlimit = 0
). 同样在对象创建过程中,我们不能丢弃speedlimit
自行车的领域只是因为Honda3
具有同名字段。我们并没有告诉编译器重写这个字段,所以编译器将同时包含speedlimit
内部字段Honda3
像这样的物体-车速限制(自行车)<=隐藏
速度限制
所以如果你指定
Honda3
对象类型的变量Bike
然后你可以访问隐藏的speedlimit
通过这个变量。请参考下面的图片来可视化整个过程-iih3973s2#
因为
obj2 = obj
分配Honda3
具有隐藏字段的示例Bike.speedlimit
初始化为默认值0
一new Bike()
用一个speedlimit
示例变量0
创建然后分配200
一new Honda3()
是用示例变量创建的speedlimit = 0
和一个Bike.speedlimit = 0
继承自Bike
那么speedlimit
已分配500
.Honda3
正在隐藏Bike
speedlimit
分配时obj = obj2
执行向上投射并引用Honda
作为一个Bike
以及System.out.prinln(obj.speedlimit)
打印Bike.speedlimit
相反地,如果你要做一个悲观的预测System.out.println(((Honda3) obj).speedlimit)
你会得到500
另外,运行时多态性或动态分派仅适用于方法而不是数据成员。方法被重写,但字段被隐藏。之后
obj = obj2
pgvzfuti3#
当您在子类中定义一个字段,该字段与超类中的字段具有相同的名称时,您不会覆盖该字段,而只是将其“隐藏”给子类的用户。
因此,当您创建一个honda3时,您将创建一个具有两个speedlimit字段的对象:bike类的字段被初始化为零(因为这是int的默认值),而honda3类的字段被设置为200。然后,当您将honda3“使用”为“bike”时,bike类的speedlimit字段将不再隐藏并打印到standard out。
gr8qqesn4#
您看到0是因为您使用了两个独立的speedlimit属性,一个用于bike类,另一个用于honda3类,您可以从honda3类中删除该属性,因为它是从bike类继承的。
在这条线上
obj.speedlimit
您正在指定bike属性,另一方面obj2.speedlimit
正在指定honda3属性。分配时obj = obj2
然后从中访问speedlimit属性obj
,您将不再使用honda3类中的属性,而是使用bike类中尚未分配的属性。如果你从honda3类中删除speedlimit属性,你的问题就会消失。