After talking with some friends and a deeper research, I found out what is the appearance that happens in this case. It’s kind of obscure and relatively hard to find, so I’ll try to explain.
The core of this behavior is a type of method, which is widely used by Java, which is known as Synthetic Method. According to the Java specification, an element is synthetic when it is produced by the compiler and does not have a corresponding source code, except for standard constructors. There are other types of synthetic structures, but let’s focus on synthetic methods.
So how do these synthetic methods solve the problem of access to a private instance variable?
Well, the java compiler will generate public methods to access ALL variables that are accessed by an innerclass. Let’s look at the previous example.
class Test{
private int myField;
private void doSomething(){
someInstance.setListener(new onClickListener(){
@Override
publicc void onClick(){
myField = 3;
}
});
}
}
We have an anonymous class that is accessing a private instance variable that will turn into something like:
class Test{
private int myField;
private void doSomething(){
someInstance.setListener(new $AnonClass(this));
}
}
class $AnonClass{
Test test;
public $AnonClass(Test test){
this.test = test;
}
public void onClick(){
//Por enquanto é mágica!
}
}
And that’s where synthetic methods come in. The compiler will create a public method in the class Test
in order to give access to the desired variable, and this method is the famous synthetic method. So, it would look something like this:
class Test{
private int myField;
private void doSomething(){
someInstance.setListener(new $AnonClass(this));
}
public int access$0000(int a){
this.myField = a;
}
}
class $AnonClass{
Test test;
public $AnonClass(Test test){
this.test = test;
}
public void onClick(){
test.access$0000(3);
}
}
I made an example that you can see this kind of method being created.
Simple example showing a class with a Main method accessing a private variable from an innerclass.
public class SyntheticMethodTest {
public static void main(String[] args){
Test test = new Test(2);
System.out.println(test.a);
Class cls = test.getClass();
for (Method field : cls.getDeclaredMethods()){
System.out.println(field);
}
}
static class Test{
private int a;
public Test(){
}
public Test(int a) {
this.a = a;
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
}
}
The output is:
2
static int SyntheticMethodTest$Test.access$000(SyntheticMethodTest$Test)
public void SyntheticMethodTest$Test.setA(int)
public int SyntheticMethodTest$Test.getA()
And there’s the static int SyntheticMethodTest$Test.access$000(SyntheticMethodTest$Test)
, which is the synthetic method created to access the variable a
.
If the line System.out.println(test.a);
is removed, method is not created.
Related What is the difference between inner class, nested class and anonymous class?
– user28595
Related: Why it is not possible to modify local variables when accessed within anonymous classes?
– user28595