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

标签 java inheritance

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

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

我知道没有覆盖的事实(私有(private)父方法对 child 不可见,所以它们只能被隐藏。)这意味着 child 不会查找层次结构来查看父的版本从子调用实例方法时的方法。
然而,与我所期望的完全相反(被调用的 child 中存在的版本)正在发生。私有(private)方法的父版本被调用。

如果通常调用子对象的实例方法,并且在子对象中有一个具有相同签名的方法(与调用 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().");
        }
    }

}

最佳答案

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

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

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

关于java - 为什么子类转换为父类型默认为私有(private)实例方法的父版本,而不是其他实例方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25805076/

相关文章:

java - 如何强制子类调用抽象实现的方法

java - 只用一个类或多个类实现接口(interface)

c++ - 构造函数 Parent 在构造函数 Child 的初始化列表中被调用

java - 继承时代码重复

AngularJS:需要复制继承的依赖项?

c++ - 我怎样才能防止这种在 C++ 中的转换

有界通配符的 Java 泛型行为

java - JavaFX 应用程序中 "<release>"的 "<configuration>"元素是什么

java - 无法解析 DateTime - 由于时区偏移转换(欧洲/柏林)导致的非法时刻

java - Bash:查找所有子目录中的所有 jar 并显示它们的文件夹、名称和大小