Що відбувається насправді (На що перетворюються класи компілятором) - 1

— Привіт, Аміго! Ось тобі ще трохи інформації.

Я вже тобі казала, що всі анонімні класи насправді перетворюються компілятором на звичайні внутрішні класи.

— Ага. Я навіть пам'ятаю, що вони мають імена – це числа: 1, 2, 3 тощо.

— Саме так. Але ще який є нюанс.

Якщо клас був оголошений усередині методу та використовував якісь змінні, то посилання на них будуть додані до згенерованого класу. Дивись сам:

Було:

Вихідний приклад:
class Car
{
 public ArrayList&ltCar> createPoliceCars(int count)
 {
  ArrayList&ltCar> result = new ArrayList&ltCar>();

  for(int i=0; i<count; i++)
  {
   final int number = i;
   result.add(new Car()
    {
     public String toString()
     {
      return ""+number;
     }
    });
  }
  return result;
 }
}

Результат компіляції:

Що згенерував компілятор:
class Car
{
 public ArrayList&ltCar> createPoliceCars(int count)
 {
  ArrayList&ltCar> result = new ArrayList&ltCar>();

  for(int i=0; i<count; i++)
  {
   final int number = i;
   result.add(new Anonymous2(number));
  }
   return result;
  }

 class Anonymous2
 {
  final int number;
  Anonymous2(int number)
 {
  this.number = number;
 }

  public String toString()
  {
   return ""+number;
  }
 }
}

Зрозумів у чому штука? Внутрішній клас неспроможна змінити локальну змінну методу, т.к. на той час, коли буде виконуватися код цього класу, ми можемо взагалі піти з методу.

Тепер другий момент. Метод toString() використовує передану змінну. Для цього довелося:

А) зберегти її всередині згенерованого класу

Б) додати її до конструктора.

— Зрозумів. Класи, оголошені всередині методу, завжди працюють із копією змінних.

— Саме!

— Тоді зрозуміло, чому змінні мають бути final. І чому їх не можна міняти. Якщо насправді ти працюєш з копією, а не з оригіналом, то користувач не зрозуміє, чому не може змінювати значення змінної, а отже, треба просто заборонити її змінювати.

— Так, мені здається, що оголошення змінних final – це невелика плата за те, що компілятор за тебе згенерує клас, передасть у нього та збереже там усі змінні методи, які ти хочеш використати.

— Згоден. Все ж таки це крута штука – анонімні локальні класи.

А якщо я оголошу всередині методу свій локальний клас і використовуватиму в ньому змінні методи, компілятор їх теж додасть цьому класу?

— Так, додасть до класу та його конструктор.

— Я так і думав.