如果变量在调试Java时在IntelliJ IDEA中具有名称“this $ 0”,这意味着什么?

在此处输入图像描述

我试图通过在调试模式下运行名为testSendStream的测试并在测试执行时逐步执行代码来了解此 Functional Reactive Java库。

上面的快照显示有一个名为this$0的奇怪命名变量。

这个名字来自哪里?

这个名字是什么意思?

为什么这个变量有这个名字?

给它这个名字背后的原因是什么?

当然这个名称不是来自代码本身,它是由IntelliJ或javac / java生成的。 但为什么 ?

如果我通过标签Mystery Object标记此对象,那么看到会发生什么也很有趣。

在此处输入图像描述

this$0Inner类中的引用,它指示使用哪个Outer类实例来创建Inner类的当前实例。

这是必要的,因为如果我们希望能够在内部类中编写类似methodFromOuterClass() ,嵌套类可以访问外部类的所有成员(包括私有类methodFromOuterClass() ,JVM需要知道应该使用哪个Outer实例来调用此方法on(因此编译器将此代码更改为此this$0.methodFromOuterClass() )。


更多细节和示例:

 public class Outer { private int id; public Outer(int id) { this.id = id;} public class Inner{ void printParentID(){ 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.printParentID(); in2.printParentID(); 

我们会看到

 1 2 

但是in1如何知道它应该从o1而不是从o2打印id值?
这是因为内部类的每个实例都知道它创建的外部类的哪个实例。 这是因为this$0引用存储了用于创建内部实例的外部实例的引用。
此变量由编译器添加到所有非静态内部类,并在调用时设置其值

 Outer.Inner in1 = o1.new Inner();//`this$0` will be set to hold `o1` instance. 

所以代码就像

 void someMethod(){ System.out.println(id); } 

基本上等于

 void someMethod(){ System.out.println(this$0.id);//although we can't access this$0 explicitly } 

这是一个与非静态内部类相关的约定。 内部类的字节码将包含对名为this$0的包范围字段的引用,该字段允许您引用封闭类的此对象。 请注意,在您的示例中, this$0与上面定义的Mystery Object this变量的Mystery Object this相同。