2

Java inner classes store the reference to the outer instance in a synthetic field:

class A {
    class B {}
}

java.util.Arrays.toString(A.B.class.getDeclaredFields())
// [final A A$B.this$0]

What I am wondering is why this field isn't generated as private.

It can't be accessed by the programmer without reflection (outside B, where A.this refers to it).

The obvious guess is that you can write something in A (outside B) which needs to access it, but I can't think of any such case.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • You should see [this](https://stackoverflow.com/questions/41303833/inner-class-in-java) – Novy Feb 08 '19 at 08:19
  • I was about to say "so that this field can be set by the outer class upon creation", but that of course would also work with private fields ... – GhostCat Feb 08 '19 at 08:24
  • @Novy Can you explain why? I don't see anything there I didn't already know. – Alexey Romanov Feb 08 '19 at 08:35
  • @Alexey Romanov The why in my point of view is because in java by default fields, method, and classes are package-private, which means they cannot be accessed from outside of their package. The A$B.this$0 is generated the genarated class is A$B as a generated field it respect the default. A$B.this$0 is a reference to your outer this(A.this). So If you are in A (outside B) you already have access the A.this. I do not know if it is what your are looking for – Novy Feb 08 '19 at 10:59
  • I believe I've found the answer. – Alexey Romanov Feb 08 '19 at 16:39

1 Answers1

1

I was thinking in the wrong direction. It isn't A that needs to access B.this$0, but potential inner classes of B itself!

If we have

class A {
    class B {
        class C {}
    }
}

then after desugaring C becomes

class A$B$C {
    final A$B this$1;

    A$B$C(A$B b) {
        this$1 = b;
    }
}

and A.this inside C has to be accessed as this$1.this$0. Alternatively, it could have two fields

    final A$B this$1;
    final A this$0;

in which case the constructor would contain this$0 = b.this$0; (this was actually what I expected before checking).

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487