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

enter image description here

I am trying to understand this Functional Java Reactive Library by running test called testSendStream in debug mode and executing code when the test runs.

The snapshot above shows that there is a strangely named variable called this$0 .

Where does this name come from?

What does this name mean?

Why does this variable have this name?

What is the reason that he gives this name?

Of course, this name does not come from the code itself, it is generated by IntelliJ or javac / java. But why?

It's also interesting to see what happens if I tag this object with the Mystery Object label.

enter image description here

+10
source share
2 answers

this$0 is a "hidden field" in the Inner class (a non-static nested class) that is used to store a reference to an instance of the Outer class that was used to create the current instance of the Inner class ..

In short, when you have

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

The Inner instance stored in inner will retain in its field this$0 reference to the Outer instance used to create it (the same reference as in the outer variable).

This is necessary because nested classes must have access to all members of external classes (including private ones). If we want to be able to write something like methodFromOuterClass(); in the inner class, the JVM needs to know on which Outer instance it should call this method. To make this possible, the compiler "changes" such code to this$0.methodFromOuterClass() .


A little more detail and an example:

 public class Outer { private int id; public Outer(int id) { this.id = id;} public class Inner{ void printOuterID(){ System.out.println(id); } } } 

Now, what will be printed here and why?

 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(); 

We'll see

 1 2 

but how did in1 know that he should print the id value from o1 and not from o2 ?
This is because each instance of the inner class knows on which instance of the outer class it was created. And this is because of the this$0 link, which stores the link to the external instance used to create the internal instance.
This variable is added to all non-static inner classes by the compiler, and its value is set when called

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

So the code is kind of

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

essentially equal

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

This convention applies to non-stationary inner classes. The bytecode of the inner class will contain a link to a field with a subfolder area named this$0 , which allows you to reference this object of the incoming class. Note in your example, this$0 matches the Mystery Object this variable defined above.

+2
source

Source: https://habr.com/ru/post/1213166/


All Articles