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

时间:2014-09-12 09:29:53

标签: java inheritance

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

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

我理解没有覆盖的事实(私人父方法对于孩子来说是不可见的,因此它们只能被隐藏。)意味着孩子不会抬头观察父母和孩子的情况。 #39;从子进程调用实例方法时的方法版本 然而,与我所期望的(正在调用的孩子中存在的版本)正好相反。调用私有方法的父版本。

如果通常调用子实例方法,为什么会发生这种情况,并且在子代中,有一个方法具有相同的签名(在这种情况下调用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().");
        }
    }

}

3 个答案:

答案 0 :(得分:2)

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

那就是说,为了回答你的实际问题,a.method2();调用A中的私有方法的原因是私有方法不是虚拟的,因为它们根本不能被覆盖。 (如果继承类甚至不知道它们,它们怎么可能呢?)因此,它们在编译时被绑定,这意味着使用声明的变量类型。 A a声明为A,但(A.B)a在编译时 转换为B.因此,您的第一个调用使用A中的私有方法,而您的第二个调用使用私有方法从B。

这两段中的事实并不相互影响,这很古怪。可能有理由期望,因为嵌套类“知道”外部类的私有成员,所以可能有一个覆盖。但事实并非如此。私有函数永远不会出现在vTable中,永远不会被覆盖。

答案 1 :(得分:0)

简短回答:因为您的B class与包含#main()方法的文件(.java)位于同一文件中。

答案 2 :(得分:0)

父类的私有方法对子类可见的原因是子类在其情况下是其父类的inner class

  

非静态嵌套类(内部类)可以访问封闭类的其他成员,即使它们被声明为私有