0

让我们看下面的代码:

public class Test {

    class A {
        public A() {}

        private void testMethod() {
            System.out.println("A");
        }
    }

    class B extends A {
        public B() { super(); }

        private void testMethod() {
            System.out.println("B");
        }
    }

    public Test() { }

    public A get() {
        return new B();
    }

    public static void main(String[] args) {
        new Test().get().testMethod();
    }
}

我希望该代码能够编写B. A改为写。

一个类可以调用它所包含的内部类的私有方法这一事实可能会让人感到奇怪(至少对我而言)(为什么它们会这样?),但我真正无法理解的是为什么多态性不不工作。

我的意思是,如果Test.main()我们可以调用A.testMethod()很明显我们也调用了B.testMethod()。Java也可以确定对象的动态类型,那么为什么Java调用声明类型的方法而不是动态类型的方法呢?可以检查此行为:

public static void main(String[] args) {
    B b = new Test().new B();
    A a = b;
    b.testMethod(); // writes B
    a.testMethod(); // writes A
}

另外,为什么只有在Test.A.testMethod()is时才会发生这种情况private

4

3 回答 3

5

您期望的行为来自虚拟方法。
私有方法永远不是虚拟的。

相反,您有两个恰好具有相同名称的不相关方法。

于 2012-09-14T14:14:10.350 回答
3

它在JLS #15.2.3中定义

如果编译时声明具有 private 修饰符,则调用模式是非虚拟的

JLS #15.4.4

如果调用模式是非虚拟的,则不允许覆盖。类 T 的方法 m 是要调用的方法。

T在您的情况下,声明的类型在哪里,而不是在运行时(在您的情况下)A对象的实际类型。B换句话说,私有方法不存在多态性。

于 2012-09-14T14:23:07.373 回答
0

在 Java 中,所有非静态方法默认都是“虚拟函数”。两种特殊的非静态方法是非虚拟的:用关键字 final 标记的,不能被覆盖,私有方法,不能被继承

http://en.wikipedia.org/wiki/Virtual_function#Java

于 2012-09-14T14:14:06.323 回答