我正在测试java中的一些多态性,代码如下:
class Base {
int value = 0;
public Base(){
System.out.println("Came Here And Value is: " + value);
addValue();
}
String addValue(){
System.out.println("Calling Bases' addValue and value is currently: " + value);
value += 10;
return "";
}
int getValue(){
return value;
}
}
class Derived extends Base{
public Derived(){
System.out.println("Calling Derived constructor and value currently is: " + value);
addValue();
}
String addValue(){
System.out.println("Came to Deriveds' addValue and value now is: " + value);
value += 20;
return "";
}
int getValue(){
return value;
}
}
public class MyClass {
public static void main(String [] args){
Base b = new Derived();
System.out.println(b.getValue());
}
}
所以这里的问题是,它打印40,但我猜它应该打印30。我的想法是:new Derive首先调用new Base,它调用addValue()
并且(正如在Base中定义的addValue()
将值相加10)当时的值应该是10。然后,Derive的addValue()
被调用,这使得值为30(因为addValue()
定义在Derive中将值相加20)。但是,Base调用了它的子addValue()
。有人能解释一下发生了什么吗?
你思维过程中的误解是大胆的:
new Derived首先调用new Base,后者调用addValue()和(因为addValue()在Base中定义的值加起来是10)当时值应该是10。然后,调用Derived的addValue(),使值为30(因为在Derived中定义的addValue()将值增加20)。
尽管 addValue
放置在基类构造函数中,但它仍然在此调用
addValue
,如下所示:
this.addValue();
嗯,这
是什么?它是一个派生
类实例。派生类的 addValue
有什么作用?它增加了 20。这就是为什么你得到40。
是的,这是多态性如何工作的一个很好的例子。
此处永远不会调用父 addValue
方法,因为重写了子方法。这称为虚拟方法调用。因此,如果调用子方法两次,则结果将为 40
。
这是因为 Derived 对 super 进行了隐式调用,但它将调用 Derived 中被覆盖的 addvalue。这就是为什么你不应该在构造函数中调用可重写的方法。
您可以通过在main()中的第一行创建一个断点并让调试器向您展示步骤来找出这一点。