Java 匿名类变量
今天我在尝试匿名课程。当我执行Java 匿名类变量,java,Java,今天我在尝试匿名课程。当我执行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(
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
}
};
}
}
当您在类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,然后通过System.out.println(super.x)将其值打印为12
代码>
然后,System.out.println(x)
实际上引用了AnonClass
的封闭实例中的x
,其值为4
它不再次打印12
的原因是x
是private
;正如书中所说:
声明为私有的类的成员不会被该类的子类继承
因此,没有类$1.x
可打印;名为x
的范围中唯一的标识符是AnonClass.x
这里有两个类:普通类AnonClass
和匿名类AnonClass$1
扩展AnonClass
这两个类都有x
字段
您还有两个对象:一个是在main
方法中实例化的AnonClass
类型,使用x=4
;另一个是在testMethod()中实例化的AnonClass$1
类型,使用x=12
打印super.x
的值时,访问第二个对象的x
字段;但是x
的值属于第一个对象,因为您的类不是静态的
,并且包含对外部类实例的隐式引用
参考资料:我认为super
只用于继承。“我想不是。”宪兵,你为什么这么想?匿名类从它们扩展的类继承而来。@AndyTurner好吧,我想我对Java的知识太多了。。。肤浅的。我无法理解这一切。java规范的哪一部分说匿名类中的非限定标识符解析为封闭类而不是匿名超类?我本以为会出现“模棱两可”的编译错误。这确实是一个有趣的问题——也是不使用双大括号初始化的另一个原因。请在实例初始值设定项中参考关于变量分辨率的JLS。下面是回答我问题的提示,我想:如果您从字段x
中删除private
,则super.x
和x
都指超级实例。只有当x
是private
时,非限定的x
才会引用封闭实例。这很有趣,它似乎在私有时增加了封装级别,在公共时允许共享。