java – 为什么匿名类即使不需要也会捕获“this”?

鉴于此代码:
class Foo {}

public class Test {
        public Foo makeFoo(String p,String q) {
                return new Foo(){
                        public void doSomething() {
                                System.out.println(p);
                        }
                };
        }
}

当你编译并运行javap -c -p’Test $1.class’时,你得到这个:

Compiled from "Test.java"
class Test$1 extends Foo {
  final java.lang.String val$p;

  final Test this$0;

  Test$1(Test,java.lang.String);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #1                  // Field this$0:LTest;
       5: aload_0
       6: aload_2
       7: putfield      #2                  // Field val$p:Ljava/lang/String;
      10: aload_0
      11: invokespecial #3                  // Method Foo."<init>":()V
      14: return

  public void doSomething();
    Code:
       0: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: aload_0
       4: getfield      #2                  // Field val$p:Ljava/lang/String;
       7: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      10: return
}

当创建匿名类时,变量p被捕获到val $p中(如预期的那样,因为它是必需的),而变量q不是(正如预期的那样,因为它不需要).但是,Test.this被捕获到这个$0,即使它不需要.这是Java规范的强制要求,还是它恰好的工作方式?为什么这样工作?

解决方法

因为它是一个内在的类,因为

An instance i of a direct inner class C of a class or interface O is associated with an instance of O,known as the immediately enclosing instance of i. The immediately enclosing instance of an object,if any,is determined when the object is created (§15.9.2).

JLS 8.1.3.

“即使他们不需要”,也不例外.

相关文章

Java中的String是不可变对象 在面向对象及函数编程语言中,不...
String, StringBuffer 和 StringBuilder 可变性 String不可变...
序列化:把对象转换为字节序列的过程称为对象的序列化. 反序...
先说结论,是对象!可以继续往下看 数组是不是对象 什么是对...
为什么浮点数 float 或 double 运算的时候会有精度丢失的风险...
面试题引入 这里引申出一个经典问题,看下面代码 Integer a ...