我正在努力理解 this通过运行 test 来实现功能性 Reactive Java 库在 Debug模式下调用 testSendStream
并在测试执行时单步执行代码。
上面的快照显示有一个名为 this$0
的奇怪命名的变量。
这个名字从何而来?
这个名字是什么意思?
为什么这个变量有这个名字?
给它起这个名字的原因是什么?
这个名字肯定不是代码本身来的,是IntelliJ或者javac/java生成的。但是为什么?
如果我用标签 Mystery Object
标记这个对象,看看会发生什么也很有趣。
最佳答案
this$0
是 Inner
类(非静态 嵌套类)中的“隐藏字段”,用于保存对实例的引用用于创建内部类的当前实例的 Outer
类。
简而言之,当你有
Outer outer = new Outer();
Outer.Inner inner = outer.new Outer.Inner();
inner
持有的 Inner
实例将在其 this$0
字段中存储对用于创建的 Outer
实例的引用它(与 outer
变量持有的引用相同)。
这是必要的,因为嵌套类必须能够访问外部类的所有成员(包括私有(private)成员)。如果我们希望能够在内部类中编写类似 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
的值?< br/>
这是因为内部类的每个实例都知道它是在哪个外部类实例上创建的。这是因为 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
字段。
关于java - 调试 Java 时,如果在 IntelliJ IDEA 中变量的名称为 "this$0",这意味着什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28462849/