为什么这段代码打印出的是20 20,而不是20 10?

3
package package1;
public class MyClassA {
    protected int size;
    public MyClassA() {
    }
    protected int getAge() {
        return 10;
    }
    public int callAge() {
        return getAge();
    }
}

package package2;
import package1.MyClassA;
public class MyClassB extends MyClassA {
    protected int getAge() {
    return 20;
    }
    private int superesult() {
        return super.callAge();
    }
    public static void main(String args[]) {
        MyClassB classb = new MyClassB();
        System.out.println(classb.getAge());
        System.out.println(classb.superesult());
    }
}

当我调用getAge和superresult方法时,我期望输出为20 10,但代码打印的是20 20。提前感谢。


4
因为 getAge 被覆盖了。 - Oliver Charlesworth
"superresult" 调用了 "MyClassA" 中的 "callAge" 方法,而 "callAge" 又调用了被覆盖的方法 "getAge"。在 "MyClassB" 中进行的重写返回值为 20。这就是重写的作用。 - khelwood
我期望得到20 10。为什么你期望这样的结果? - Pshemo
1
@Pshemo:我认为OP的意思是,如果你通过super调用某些东西,你会在“上级域”中改变上下文,也就是说所有的调用现在都在“超级域”中。 - Willem Van Onsem
这里需要理解的概念是多态性。意思是:没有必要问为什么事情是这样的,更像是:这就是多态在Java中的表现方式。因此,您必须学习该概念的工作原理;然后您将理解您正在观察的行为。 - GhostCat
3个回答

5

简短回答:您可以直接调用A中实现的callAge方法。但是该方法会调用被重写的getAge方法(因此Java会按照在B中的实现方式执行)。

详细说明

当您调用:

classb.superesult();

它将调用super.callAge(),这意味着类A的callAge()被执行。他的部分中的callAge()调用getAge(),但由于对象是类B的实例并且getAge()被覆盖,它返回20
请注意,如果您调用super.foo(),则仅调用超级foo。因此,super并不意味着您“更改上下文”:所有结果出自超级调用的调用仍通过对象进行动态绑定(而对象仍是类B的实例)。 foo进行的所有调用都可以被重写(除非这些标记为final)。在大多数情况下,这是期望的行为。

3

这是多态性。您已在getAge()方法中进行了覆盖。因此,当您调用该方法时,覆盖的方法始终执行。

Java虚拟机(JVM)为每个变量引用的对象调用适当的方法。它不会调用由变量类型定义的方法。这种行为被称为虚拟方法调用,并展示了Java语言中重要的多态性特征之一。


1
因为你在子类中覆盖了getAge()方法。现在,由于MyClassB classb = new MyClassB();指向子类,所以它的方法将被调用,而不是父类的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接