我今天正在尝试匿名课程。当我System.out.println(super.x);
时,它会打印12,当我使用System.out.println(x);
时,它会打印4.我认为super.x
会打印4,并且想知道是否有人可以向我解释为什么会这样?
public class AnonClass {
private int x = 1;
public AnonClass(int x) {
this.x = x;
}
public static void main(String[] args) {
AnonClass test = new AnonClass(4);
test.testMethod();
}
public void testMethod() {
AnonClass anon = new AnonClass(12) {
{
System.out.println(super.x); //Prints 12
System.out.println(x); //prints 4
}
};
}
}
答案 0 :(得分:11)
在class AnonClass
内定义这样的匿名类时:
AnonClass anon =
new AnonClass(12) {
{
System.out.println(super.x); //Prints 12
System.out.println(x); //prints 4
}
};
编译器将创建一个类似这样的类:
class AnonClass$1 extends AnonClass {
final AnonClass enclosed;
AnonClass$1(AnonClass enclosed, int x) {
super(x);
System.out.println(super.x);
System.out.println(enclosed.x);
this.enclosed = enclosed;
}
}
然后调用它:
AnonClass anon = new AnonClass$1(this, 12);
请注意,超级构造函数(super(x);
)的调用发生在实例初始化程序(System.out.println
行)的内容之前。
因此,超级构造函数将字段AnonClass.x
初始化为12,然后通过12
将其值打印为System.out.println(super.x);
。
然后,System.out.println(x)
实际上引用x
的封闭实例中的AnonClass
,其值为4.
再次打印12
的原因是x
为private
;正如它在JLS Sec 8.2中所说的那样:
声明为private的类的成员不会被该类的子类继承。
所以没有AnonClass$1.x
可以打印;名为x
的范围中唯一的标识符是AnonClass.x
。
答案 1 :(得分:1)
这里有两个课程:常规课程AnonClass
和匿名课程AnonClass$1
AnonClass
这两个类都有x
字段
您还有两个对象:一个AnonClass
类型main
方法实例化x = 4
方法,AnonClass$1
类型testMethod()
实例化x = 12
super.x
{ {1}}
当您打印x
的值时,您正在访问第二个对象的x
字段;但static
的值属于第一个对象,因为您的类不是Block
并且包含对外类实例的隐式引用