Java 为什么强制转换为父类型的子类默认为私有实例方法的父版本,而不是其他实例方法的父版本?
我的理解是,对父类型的子类型转换(如Java 为什么强制转换为父类型的子类默认为私有实例方法的父版本,而不是其他实例方法的父版本?,java,inheritance,Java,Inheritance,我的理解是,对父类型的子类型转换(如Super sc=new child();)将调用父类的静态方法,并访问父类的非隐藏字段,但将使用子类的实例方法 对于私有实例方法(由于父方法是私有的,所以实际上不会发生重写的方法)来说,这似乎不成立 我理解没有重写(私有父方法对子对象不可见,因此只能隐藏它们)这一事实意味着,当从子对象调用实例方法时,子对象不会查找继承权以查看父对象的方法版本。 然而,与我所期望的完全相反的情况(在被调用的孩子中出现的版本)正在发生。调用私有方法的父版本 如果子类的实例方法通
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().");
}
}
}
简短回答:因为您的
B类
与包含#main()
方法的类位于同一个文件(.java)中。父类的私有方法对子类可见的原因是,在您的情况下,子类是其父类的私有方法
非静态嵌套类(内部类)可以访问封闭类的其他成员,即使它们声明为私有
首先,B实际上是一个嵌套类,奇怪的是,外部类可以访问嵌套类的私有成员。否则,执行
((A.B)A.method2())甚至是不合法的代码>(反之亦然。B也可以访问A中的私有成员。)
也就是说,要回答您的实际问题,原因是a.method2()代码>调用中的私有方法是因为私有方法不是虚拟的,因为它们根本不能被重写。(如果继承类甚至不应该知道它们,它们怎么可能呢?)A
声明为A,但(A.B)A
在编译时被强制转换为B。因此,第一次调用使用A的私有方法,第二次调用使用B的私有方法
奇怪的是,这两段中的事实并没有相互影响。可以合理地预期,由于嵌套类“知道”外部类的私有成员,因此可以进行重写。但事实并非如此。私有函数永远不会显示在vTable中,也永远不会被重写