为什么子类转换为父类型默认为私有实例方法的父版本,而不是其他实例方法?

Mer*_*Mer 5 java inheritance

我的理解是,子类型转换为父类型(如Super sc = new Child();)将调用父类的静态方法,并访问父类的非隐藏字段,但会使用子类的实例方法.

对于私有实例方法(由于父方法是私有的,实际上不会发生覆盖的情况),这似乎不适用.)

我理解没有覆盖的事实(私有父方法对于孩子是不可见的,因此它们只能被隐藏.)意味着孩子不会查找层次结构以查看父方法的方法版本.从子进程调用实例方法.
然而,正如我所期望的那样(正在调用的孩子中出现的版本)正好相反.调用私有方法的父版本.

如果通常调用子项的实例方法,为什么会发生这种情况,并且在子项中,有一个方法具有相同的签名(method2()在这种情况下是完全匹配),在父项中隐藏相同的方法类?

package whatever;

public class A {

    public void method1(){
        System.out.println("A method1().");
    }
    //using "final" here to emphasize that this is a hiding, not an override. 
    private final void method2(){  
        System.out.println("A private method2().");
    }

    public static void main(String[] args)
    {
        A a = new A().new B();
        a.method1(); //calls B  method 1
        ((A.B)a).method1(); //calls B method 1 
        a.method2(); //calls A private method 2 **I expected it to call B private method 2
        ((A.B)a).method2(); //calls B private method 2

    }

    public class B extends A {

        public void method1(){
            System.out.println("B method1().");
        }
        private final void method2(){
            System.out.println("B private method2().");
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

Joã*_*des 2

首先,B 实际上是一个嵌套类,奇怪的是,嵌套类的私有成员可以被外部类访问。否则,这样做甚至不合法((A.B)a).method2();(反之亦然。B 也可以访问 A 中的私有成员。)

也就是说,为了回答您的实际问题,a.method2();调用 A 中的私有方法的原因是私有方法不是虚拟的,因为它们根本不能被重写。(如果继承类根本不应该知道它们,它们怎么可能是这样?)因此,它们在编译时绑定,这意味着使用变量的声明类型。A a声明为 A,但在编译时(A.B)a强制转换为 B。因此,您的第一次调用使用 A 中的私有方法,第二次调用使用 B 中的私有方法。

奇怪的是,这两段中的事实并不相互影响。可以合理地预期,由于嵌套类“知道”外部类的私有成员,因此可能会进行覆盖。但事实并非如此。私有函数永远不会出现在 vTable 中,也永远不会被覆盖。