1

这是继承的代码示例,代码功能正常。我无法理解此代码的输出,请向我解释。

class R {
    private void S1() {
        System.out.println("R:S1");
    }

    protected void S2() {
        System.out.println("R:S2");
    }

    protected void S1S2() {
        S1();
        S2();
    }
}

class S extends R {
    private void S1() {
        System.out.println("S:S1");
    }

    protected void S2() {
        System.out.println("S:S2");
    }
}

public class Inheritance {
    public static void main(String srgs[]) {
        new S().S1S2();
    }
}

输出是:

R:S1
S:S2

为什么第一次调用 R 类的 S1 而第二次调用 S 类的 S2。

4

2 回答 2

3

R.S1private,所以它不会被多态调用,S.S1也不会覆盖它。

R.S2受保护的,所以S.S2覆盖它,当你调用S2一个实例时S2(即使它只是静态地知道是一个实例R),S.S2将被调用。

JLS 的第 8.4.8.1 节

在类 C 中声明的实例方法 m1 覆盖在类 A 中声明的另一个实例方法 m2,前提是满足以下所有条件:

  • C 是 A 的子类。

  • m1 的签名是 m2 签名的子签名(第 8.4.2 节)。

  • 任何一个:

    • m2 是公共的、受保护的或在与 C 相同的包中声明为具有默认访问权限,或

    • m1 覆盖方法 m3(m3 不同于 m1,m3 不同于 m2),这样 m3 会覆盖 m2。

注意m2不能是私人的。

于 2012-08-10T20:08:42.283 回答
0

在 R 中,S1 是私有的,因此不能被覆盖。因此,在 R#S1S2 中对 S1 的调用总是调用 R#S1。S 中的 S1 完全不相关。[旁注:你需要更好的名字。]

但是 S2 不是私有的,所以它可以被覆盖 - 它是。

由于知道私有函数不能被覆盖,Java VM 可以获得良好的性能提升。任何东西,甚至是后代类,都不应该受到类的私有细节的影响。

于 2012-08-10T20:13:51.310 回答