Java 为什么从超类调用时会调用子类中的方法?
我的代码如下所示:Java 为什么从超类调用时会调用子类中的方法?,java,polymorphism,overriding,Java,Polymorphism,Overriding,我的代码如下所示: public abstract class BaseClass{ public void update() { //... } public void somethingHappenedSoCallUpdate() { update(); } } public class ExtendingClass extends BaseClass{ @Override public void update() { //..
public abstract class BaseClass{
public void update() {
//...
}
public void somethingHappenedSoCallUpdate() {
update();
}
}
public class ExtendingClass extends BaseClass{
@Override
public void update() {
//...
}
}
有一个
ExtendingClass
的实例,在某个点上调用了方法somethingHappenedSocalUpdate()
。我希望该方法将调用BaseClass.update()
,但是调用了ExtendingClass.update()
。有人能解释一下原因吗?这是多态性:根据对象的实际类型在运行时调用正确的方法,这是一个动态绑定。您重写了该方法,因此如果仍希望抽象类中的代码运行,则需要在重写的方法中隐式调用update()
。所以
public class ExtendingClass extends BaseClass {
@Override
public void update() {
super.update(); // Call the base method.
}
}
希望有帮助:)
我希望该方法将调用
BaseClass.update()
,但是调用了ExtendingClass.update()
。有人能解释一下原因吗
因为Java就是这样定义的。默认情况下,所有非私有方法都是虚拟的,这意味着当您重写了方法时,在实例上调用的方法是实例的最重写版本(ExtendingClass
,在您的情况下),而不考虑方法调用所通过的类型引用。这是现代OOP语言中多态性的基础
编译时类型引用告诉编译器代码是否有权访问该方法;对象的运行时类型告诉JVM要调用的方法的哪个重写
让我们举一个简单的例子:
class Base {
public void method1() {
System.out.println("Base#method1");
}
}
class Derived extends Base {
@Override
public void method1() {
System.out.println("Derived#method1");
}
public void method2() {
System.out.println("Derived#method1");
}
}
// Usage:
Base b = new Derived();
b.method1(); // Calls Derived#method1, the most-overridden version the
// actual object has
b.method2(); // Fails to compile; Base doesn't define method2, so the
// code doesn't have access to call it when using a Base
// reference, even though the object does have the method
正如@hyde所说,Java方法是虚拟的,这意味着VM在运行时决定调用哪个方法。如果对扩展了
BaseClass
的实例调用somethingHappenedLocallUpdate()
,则将调用BaseClass.somethingHappenedLocallUpdate()
,但由于ExtendingClass
重写了BaseClass.update()
它将初始化ExtendingClass.update()
而不是BaseClass.update()
扩展方法时,您必须这样考虑:
每当你扩展一个方法,把它放在一个堆栈上,当你调用它时,Java就会查看这个“堆栈”并调用最上面的。这意味着,如果您有一个
BaseClass
具有update()
方法,则可以通过X个类扩展该类,而不是覆盖update()
方法,但如果X+1类覆盖该方法,Java将始终调用X+1的方法。因为您在子类中重写了update,并且由于Java方法是虚拟重写的,所以调用了version
选项1
覆盖更新,覆盖发生的某些事情局部更新()方法,并在那里使用super.update()
而不是update()
选项2
在超类中将更新设为私有:
private void update()
在Java中,方法是虚拟的。查找这意味着什么。“我希望该方法将调用BaseClass.update()”-为什么?因为SomethingHappenedSocalUpdate方法仅在基类中定义