众所周知,私有字段不是在类之间继承的。引起我兴趣的是它对内部静态类的作用。 请考虑以下代码:
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
}
}
}
您能否解释一下如何访问其他内部类的私有字段?如果它是合法的,为什么只能通过" super.XXX"构造
答案 0 :(得分:3)
内部类是Java的后期入门。添加它们时,它们仅作为编译器扩展添加,不对JVM进行更改。
语言规范声明允许内部类访问在其中声明的类的私有成员;包括其他内部类。
为了使其工作,编译器生成桥接方法。在上面的示例中使用带有Main $ A的javap如下所示:
注意添加访问$ 200并访问$ 300。它们分别提供对私有方法和字段的后门访问。
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的生成代码。注意访问$ 200和300的调用,它们出现在super.a和super.foo()出现在Java代码中。
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
}
如果它是合法的,为什么只能通过&#34; super.XXX&#34;构造
私有字段通常不是字段的编译器解析路径的一部分,通过强制开发人员指定super,编译器确保私有访问是有意义的而不是错误。
答案 1 :(得分:0)
From JLS3 6.6.1:“私有类成员或构造函数只能在顶级类(第7.6节)的主体内访问,它包含成员或构造函数的声明。它不是由子类继承的。
由于内部类可以在顶级类的主体内访问,因此它的可访问类和子类不在封闭类中。 现在规范没有说明这应该如何发生 - 这不是规范的工作。真正由实现程序员来实现它,并且这些细节没有记录在当前的规范中。