所以我对javac(版本1.7.0_65)生成的访问器有一个问题,允许内部类访问外部类的私有字段。
首先,这是一个简短的代码片段:
public class A {
private int f = 0;
class AA {
public int m() {
return f;
}
}
}
编译器在类A中生成一个访问器方法,以便方法m能够读取并返回f的值。
此访问器如下所示:
static int access$0(A);
flags: ACC_STATIC, ACC_SYNTHETIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #12 // Field f:I
4: ireturn
我的问题是:为什么这个访问器是作为静态方法生成的?是否存在非静态方法不起作用的情况?
答案 0 :(得分:0)
这是因为在程序加载运行之前,必须在内存中支持代码的任何方法(这样就不会发生编译错误)。我们知道,静态方法在非静态成员(变量和方法)之前加载到内存中。此外,JVM线程调用该访问器方法。 JVM线程可以访问静态方法。
答案 1 :(得分:0)
IMO(至少)有两个理由做出这个决定:
首先:如果方法不是静态的,那么子类可能会覆盖它!
由于编译器无法确定运行时的类与编译时看到的类相同,因此无法生成一致的不相交命名。
考虑这个例子:
public class A {
private int x = 1;
private class AA {
public int f() {
return x; // would call access$0 on the outer instance
}
}
public int getX() {
return new AA().f();
}
}
public class B extends A {
private int y = 2;
private class BB {
public int g() {
return y;
}
}
}
如果方法不是静态的,则以下代码将导致2而不是1:
assertEquals(new B().getX(), 2);
第二:访问器方法也必须可用于静态内部类。