Given this code:
class Foo {}
public class Test {
public Foo makeFoo(String p, String q) {
return new Foo(){
public void doSomething() {
System.out.println(p);
}
};
}
}
When you compile that and run javap -c -p 'Test$1.class'
, you get this:
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
}
When the anonymous class is created, the variable p
is captured into val$p
(as expected, because it's needed), and the variable q
is not (as expected, because it's not needed). However, Test.this
is captured into this$0
even though it isn't needed. Is this mandated by the Java specification, or is it just the way it happens to work? Why does it work this way?