以下几段代码,运行结果分别是什么?
code1:
class Sub extends Super{
public void f() {System.out.println("Sub's public f()");}
}
public class Super{
public void f() {System.out.println("Super's public f()");}
public static void main(String[] args){
Super po = new Sub();
po.f();
}
}
code2:
class Sub extends Super{
private void f() {System.out.println("Sub's private f()");}
}
public class Super{
public void f() {System.out.println("Super's public f()");}
public static void main(String[] args){
Super po = new Sub();
po.f();
}
}
code3:
class Sub extends Super{
public void f() {System.out.println("Sub's public f()");}
}
public class Super{
private void f() {System.out.println("Super's private f()");}
public static void main(String[] args){
Super po = new Sub();
po.f();
}
}
code4:
class Sub extends Super{
private void f() {System.out.println("Sub's private f()");}
}
public class Super{
private void f() {System.out.println("Super's public f()");}
public static void main(String[] args){
Super po = new Sub();
po.f();
}
}
答案:
code1: Sub's public f()
code2: Compiled error
code3: Super's private f()
code4: Super's public f()
说明:
这个问题困扰了我很久。
通过以往的学习我知道Super po = new Sub()的时候"Method is Sub's,Field is Super's"。但碰上域限定符时就又糊涂了。显然是知其然不知其所以然。
而当我用"javap -verbose"调试并分析日志的时候,我终于明白了:>
javap -verbose Super
Constant pool:
const #5 = class #27; // Sub
const #6 = Method #5.#21; // Sub."<init>":()V
const #7 = Method #10.#28; // Super.f:()V
public static void main(java.lang.String[]);
Code:
Stack=2, Locals=2, Args_size=1
0: new #5; //class Sub
3: dup
4: invokespecial #6; //Method Sub."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #7; //Method f:()V
由此可见,
不管是哪种情况(code1,3-4),po.f()都会无条件先调用Super.f()。
此时据我估计,JVM会去Sub中寻找可访问的相同修饰符的函数。如果找到则用其替代Super.f()运行。
而成员变量不存在这种机制。