如果在 IntelliJ IDEA 中调试 Java 时变量的名称为 "this[=10=]",这意味着什么?

What does it mean if a variable has the name "this$0" in IntelliJ IDEA while debugging Java?

我试图理解 this Functional Reactive Java library by running a test 在调试模式下调用 testSendStream 并在测试执行时单步执行代码。

上面的快照显示有一个名为 this[=13=] 的奇怪命名的变量。

这个名字从何而来?

这个名字是什么意思?

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

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

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

如果我用标签 Mystery Object 标记这个对象,看看会发生什么也很有趣。

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

this[=17=] 是 "hidden field" in Inner class(非静态 嵌套 class)用于保存对 Outer class 实例的引用,该实例用于创建内部 class.

的当前实例

简而言之,当你有

Outer outer = new Outer();
Outer.Inner inner = oc.new Outer.Inner(); 

Innerinner 持有的实例将在其 this[=17=] 字段中存储对用于创建它的 Outer 实例的引用(与 [=24= 持有的引用相同) ]变量)。

这是必要的,因为嵌套的 classes 必须能够访问外部 classes 的所有成员(包括私有成员)。如果我们希望能够在内部 class 中编写类似 methodFromOuterClass(); 的内容,JVM 需要知道它应该在哪个 Outer 实例上调用此方法。使编译器 "changes" 这样的代码成为可能 this[=27=].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 的值?
这是因为 inner class 的每个实例都知道它是在 outer class 的哪个实例上创建的。这是因为 this[=17=] 引用存储了对用于创建内部实例的外部实例的引用。
此变量由编译器添加到所有非静态内部 classes,并在您调用

时设置其值
Outer.Inner in1 = o1.new Inner(); //`this[=14=]` will be set to hold `o1` instance.

所以代码像

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

本质上等于

void printOuterID(){
    System.out.println(this[=16=].id); //although we can't access this[=16=] explicitly
}