匿名类变量

时间:2016-10-11 20:22:09

标签: 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(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
            }
        };

    }
}

2 个答案:

答案 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的原因是xprivate;正如它在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并且包含对外类实例的隐式引用

参考:Nested Classes in Java