众所周知,类之间不继承私有(private)字段。令我感兴趣的是它如何用于内部静态类。 考虑以下代码:
public class Main {
public static void main(String[] args) {
new B();
}
private static class A {
private int a = 10;
private void foo() {
System.out.println("A.foo");
}
}
private static class B extends A {
{
// foo(); // compile-time error
super.foo(); // ok
// System.out.println(a); // compile-time error
System.out.println(super.a); // ok
}
}
}
您能解释一下如何访问其他内部类的私有(private)字段吗?如果它是合法的,为什么只能通过“super.XXX”构造才能实现?
最佳答案
内部类是后来进入 Java 的入口。添加它们时,它们仅作为编译器扩展添加,对 JVM 没有任何更改。
语言规范声明内部类被允许访问它在其中声明的类的私有(private)成员;这包括其他内部类。
为了让它工作,编译器生成桥接方法。将 javap 与上面示例中的 Main$A 一起使用看起来像这样:
请注意增加了 access$200 和 access$300。它们分别提供对私有(private)方法和字段的后门访问。
class Main$A {
Main$A(Main$1);
Code:
0: aload_0
1: invokespecial #3 // Method "<init>":()V
4: return
static void access$200(Main$A);
Code:
0: aload_0
1: invokespecial #2 // Method foo:()V
4: return
static int access$300(Main$A);
Code:
0: aload_0
1: getfield #1 // Field a:I
4: ireturn
}
为了完整起见,这里是 Main$B 的生成代码。请注意对 access$200 和 300 的调用,它们出现在 Java 代码中出现 super.a 和 super.foo() 的位置。
class Main$B extends Main$A {
public Main$B();
Code:
0: aload_0
1: aconst_null
2: invokespecial #1 // Method Main$A."<init>":(LMain$1;)V
5: aload_0
6: invokestatic #2 // Method Main$A.access$100:(LMain$A;)V
9: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
12: aload_0
13: invokestatic #4 // Method Main$A.access$200:(LMain$A;)I
16: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
19: return
}
And if it is legal, why it is possible only via "super.XXX" construct?
私有(private)字段通常不是字段的编译器解析路径的一部分,通过强制开发人员指定 super,编译器确保私有(private)访问是本意而不是错误。
关于java - 访问父类(super class)的私有(private)字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25991377/