this$0
是Inner
类(非静态嵌套类)中的“隐藏字段”,用于保存对创建当前Inner
类实例的Outer
类实例的引用。
简而言之,当您拥有:
Outer outer = new Outer();
Outer.Inner inner = outer.new Outer.Inner();
Inner
的实例由inner
持有,在其this$0
字段中存储对创建它的Outer
实例的引用(与outer
变量持有的引用相同)。methodFromOuterClass();
这样的代码,JVM需要知道应该在哪个Outer
实例上调用此方法。为了使它成为可能,编译器将这样的代码“更改”为this$0.methodFromOuterClass()
。
public class Outer {
private int id;
public Outer(int id) { this.id = id;}
public class Inner{
void printOuterID(){
System.out.println(id);
}
}
}
Outer o1 = new Outer(1);
Outer o2 = new Outer(2);
Outer.Inner in1 = o1.new Inner();
Outer.Inner in2 = o2.new Inner();
in1.printOuterID();
in2.printOuterID();
1
2
in1
如何知道它应该从 o1
而不是 o2
中打印 id
的值呢?this$0
引用引起的,该引用存储对用于创建内部实例的外部实例的引用。Outer.Inner in1 = o1.new Inner(); //`this$0` will be set to hold `o1` instance.
所以像这样的代码
void printOuterID(){
System.out.println(id);
//OR
//System.out.println(Outer.this.id);
}
void printOuterID(){
System.out.println(this$0.id); //although we can't access this$0 explicitly
}
顺便提一下,如果您的内部类不需要访问其任何外部类的非静态成员,则可以将其更改为static class
,这将摆脱this$0
字段。
这与非静态内部类相关的惯例有关。 内部类的字节码将包含对名为this$0
的包作用域字段的引用,该字段允许您引用封闭类的this对象。 请注意,在您的示例中,this$0
与上面定义的Mystery Object this
变量相同。
Outer.this
,而且可以将内部类定义为 静态 嵌套类。有时候会忘记使用static
关键字。 - Joop Eggen