Ответ 1
(Редактирование: добавлено в ответ, чтобы ответить на некоторые комментарии)
Компилятор берет внутренние классы и превращает их в классы верхнего уровня. Поскольку частные методы доступны только для внутреннего класса, компилятор должен добавить новые "синтетические" методы, которые имеют доступ к уровню пакета, чтобы классы верхнего уровня имели к нему доступ.
Что-то вроде этого (добавляются компилятором $):
class A
{
private void f()
{
final B b;
b = new B();
// call changed by the compiler
b.$g();
}
// method generated by the compiler - visible by classes in the same package
void $f()
{
f();
}
}
class B
{
private void g()
{
final A a;
a = new A();
// call changed by the compiler
a.$f();
}
// method generated by the compiler - visible by classes in the same package
void $g()
{
g();
}
}
Нестатические классы одинаковы, но у них есть добавление ссылки на внешний класс, чтобы на него можно было вызвать методы.
Причина, по которой Java делает это так, заключается в том, что они не хотят требовать изменений в VM для поддержки внутренних классов, поэтому все изменения должны были быть на уровне компилятора.
Компилятор берет внутренний класс и превращает его в класс верхнего уровня (таким образом, на уровне VM нет такого понятия, как внутренний класс). Затем компилятор должен сгенерировать новые методы "пересылки". Они создаются на уровне пакета (не общедоступны), чтобы обеспечить доступ к ним только для классов в одном пакете. Компилятор также обновил вызовы методов для частных методов для сгенерированных методов "пересылки".
Вы можете избежать того, чтобы компилятор сгенерировал метод, объявляющий методы как "пакет" (отсутствие публичных, частных и защищенных). Недостатком этого является то, что любой класс пакета может вызывать методы.