Java 为什么在超级上下文中调用私有方法?
使用此代码:Java 为什么在超级上下文中调用私有方法?,java,inheritance,Java,Inheritance,使用此代码: public abstract class A { private String runNow() { return "High"; } public abstract String cos(); static class B extends A { public String runNow() { return "Low"; } public String
public abstract class A {
private String runNow() {
return "High";
}
public abstract String cos();
static class B extends A {
public String runNow() {
return "Low";
}
public String cos() {
return "cos from B";
}
}
public static void main(String args[]) {
A[] a = new B[] {new B(), new C()};
for (A aa : a) {
System.out.println(aa.runNow() + " " + aa.cos());
}
}
}
class C extends A.B {
public String runNow() {
return "Out";
}
public String cos() {
return "cos from C";
}
}
为什么调用了类A
中的runNow
方法而不是子类中的方法?简短的回答是“因为runNow()
是私有的
”
编译此调用时,aa.runNow()
编译器会看到class A
具有runNow
私有方法,并且您的代码正在调用此私有方法。由于私有方法不能被重写,编译器将调用路由到A
的runNow()
方法-它知道在该上下文中唯一存在的方法
B
和C
也以相同的名称引入它们的方法,这一事实对编译器来说并不重要,因为这些方法在子类中是新的。编译器不考虑它们的重写而不破坏对这是因为RunNoW()是A类中的一个私有方法。 私有方法未继承,因此无法重写
private String runNow(){
return "High";
}
并且您已经创建了一个类型为a的引用
A[] a=new B[]{new B(),new C()};
因此,将被调用以完成调用的唯一runNow()是类A,因为编译器不知道类B和C中的runNow()方法,这是因为类A中的方法
runNow()
是私有的,所以在类B和C中您不会重写它。当您调用方法aa.runNow()
时,它直接从类A调用
尝试做一些实验,并将课堂上的方法更改为:
private String runNow2() {
return "High";
}
public String runNow() {
return "High";
}
同时将您的系统.out
更改为此系统:
System.out.println(aa.runNow() + " " + aa.cos() + " " + aa.runNow2());
现在结果将如预期的那样
希望有帮助
为什么从类A调用runNow方法而不是从子类调用
private
方法不在子类中继承。因此,它们不能被覆盖。由于运行时多态性仅适用于重写的方法,因此将始终调用A
中的runNow
方法。将A
中的runNow
方法更改为public
方法,您将获得所需的输出,因为public
方法是继承的,并且可以被覆盖。正如前面所说的,问题是runNow()
是私有的。因此,它不会被重写,通过类型为a
的引用访问它将获得a
类的定义,而尝试通过B
引用访问它将获得子类
不过,我想指出,这种“奇怪”行为之所以可能,是因为执行所有这些操作的方法(您的
main
方法)是在A
内部定义的。如果您的main
方法位于可以访问这些类的另一个类中,您将得到一个错误,表明该方法根本不可访问。如果您仔细想想,您可能会更清楚为什么B
和C
中的runNow()
方法不会覆盖A
中的方法。从A之外的任何对象的角度来看,根本没有runNow()
方法-它是一个实现细节,而不是A
契约的一部分。因此,它不能被重写,B
和C
中的runNow()
只是新方法,当您以多态方式使用B
和C
作为A
可能重复的方法时,您无法访问这些方法。请阅读重复的问题,了解您为什么不能重写私有方法。下次:用@Override
注释你的方法,这样编译器就可以检查你是否真的重写了一个方法。请不要编辑你的问题来引入语法错误。你不能将你的A[]
arrayaa
@MGorgon命名请阅读