为什么匿名类即使不需要也会捕获"this"?

Jos*_*ica 7 java anonymous-class

鉴于此代码:

class Foo {}

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

当你编译并运行时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
}
Run Code Online (Sandbox Code Playgroud)

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

use*_*421 6

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

类或接口O的直接内部类C的实例i与O的实例相关联,称为i的直接封闭实例.在创建对象时确定对象的直接封闭实例(如果有)(第15.9.2节).

JLS 8.1.3.

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

  • @Eugene请引用.在任何情况下,问题都是关于匿名内部类,而不是lambdas,这个答案也是如此. (3认同)