Why can nested child classes access private members of their parent class, but grandchildren cannot?
可能类似于问题,为什么外部Java类可以访问内部类私有成员?或者使用子类中的super关键字访问超类私有字段。
但是有一些区别:子类可以访问其父类(并且只能访问最近的父类)的私有成员。
给出下面的示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | public class T { private int t; class T1 { private int t1; public void test() { System.out.println(t); } } class T2 extends T1 { private int t2; public void test() { System.out.println(t); System.out.println(super.t1); System.out.println(this.t2); } } class T3 extends T2 { public void test() { System.out.println(t); System.out.println(super.t1); // NG: t1 Compile error! Why? System.out.println(super.t2); // OK: t2 OK } } } |
聪明的例子!但这实际上是一个有点无聊的解释——没有能见度问题,你根本没有办法直接从
这两种方法都在
相反,这在
1 |
如果允许
1 |
if I'd define 3 classes,
A ,B ,C ,A having a protected fieldt1 andB would inherit fromA andC fromB ,C could refer toA st1 by invokingsuper.t1 because it′s visible here. logically shouldn't the same apply to inner classes inheritance even if the field are private, because these private members should be visible due to being in the same class?
(为了简单起见,我将继续使用OP的
如果
即使对于一个
Sythetic访问方法
从技术上讲,在JVM级别上,您不能访问其他类的任何
借助于这种编译器生成的
在JDK版本1.1中引入了EDCOX1的48属性,以支持嵌套类,在Java中是一种新的语言特征。从那时起,JLS明确允许顶级类中的所有成员相互访问,包括
但为了向后兼容,编译器解包嵌套类(例如到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | class T { private int t; T() { // generated super(); // new Object() } static synthetic int access$t(T t) { // generated return t.t; } } class T$T1 { private int t1; final synthetic T t; // generated T$T1(T t) { // generated this.t = t; super(); // new Object() } static synthetic int access$t1(T$T1 t$t1) { // generated return t$t1.t1; } } class T$T2 extends T$T1 { private int t2; { System.out.println(T.access$t((T) this.t)); // t System.out.println(T$T1.access$t1((T$T1) this)); // super.t1 System.out.println(this.t2); } final synthetic T t; // generated T$T2(T t) { // generated this.t = t; super(this.t); // new T1(t) } static synthetic int access$t2(T$T2 t$t2) { // generated return t$t2.t2; } } class T$T3 extends T$T2 { { System.out.println(T.access$t((T) this.t)); // t System.out.println(T$T1.access$t1((T$T1) this)); // ((T1) this).t1 System.out.println(T$T2.access$t2((T$T2) this)); // super.t2 } final synthetic T t; // generated T$T3(T t) { // generated this.t = t; super(this.t); // new T2(t) } } |
注意:不允许直接引用
很好的发现!我认为,我们都假定您的代码示例应该编译。
不幸的是,事实并非如此……JLS在第15.11.2节中给出了答案。"使用super(emphasis mine)访问超类成员:
Suppose that a field access expression super.f appears within class C, and the immediate superclass of C is class S. If f in S is accessible from class C (§6.6), then super.f is treated as if it had been the expression this.f in the body of class S. Otherwise, a compile-time error occurs.
提供了可访问性,因为所有字段都在同一封闭类中。它们可以是私有的,但仍然可以访问。
问题是,在