我们来看下面的代码:
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()
为private
?
答案 0 :(得分:5)
您期望的行为来自虚拟方法 私有方法永远不会是虚拟的。
相反,你有两个不相关的方法碰巧具有相同的名称。
答案 1 :(得分:3)
如果编译时声明具有private修饰符,则调用模式为非虚拟
如果调用模式是非虚拟的,则不允许覆盖。类T的方法m是要调用的方法。
其中T
是声明的类型,在您的情况下为A
,而不是在运行时对象的实际类型(在您的情况下为B
)。换句话说,私有方法没有多态性。
答案 2 :(得分:0)
在Java中,默认情况下所有非静态方法都是“虚函数”。 两种特殊的非静态方法是非虚拟的:那些 标记为关键字final,无法覆盖,和私有 方法,不是遗传的。