— Привет, Амиго! Вот тебе еще немного информации.
Я уже тебе говорила, что все анонимные классы на самом деле превращаются компилятором в обычные внутренние классы.
— Ага. Я даже помню, что у них имена – это числа: 1, 2, 3 и т.д.
— Именно так. Но вот еще какой есть нюанс.
Если класс был объявлен внутри метода и использовал какие-то переменные, то ссылки на них будут добавлены в сгенерированный класс. Смотри сам:
Было:
class Car
{
public ArrayList<Car> createPoliceCars(int count)
{
ArrayList<Car> result = new ArrayList<Car>();
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<Car> createPoliceCars(int count)
{
ArrayList<Car> result = new ArrayList<Car>();
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 – это небольшая плата за то, что компилятор за тебя сгенерирует класс, передаст в него и сохранит там все переменные метода, которые ты хочешь использовать.
— Согласен. Все-таки это крутая штука – анонимные локальные классы.
А если я объявлю внутри метода свой локальный класс и буду в нем использовать переменные метода, компилятор их тоже добавит этому классу?
— Да, добавит в класс и его конструктор.
— Я так и думал.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ