JavaRush/Курсы/Java Multithreading/Что происходит на самом деле (Во что превращаются классы ...

Что происходит на самом деле (Во что превращаются классы компилятором)

Открыта
Что происходит на самом деле (Во что превращаются классы компилятором) - 1

— Привет, Амиго! Вот тебе еще немного информации.

Я уже тебе говорила, что все анонимные классы на самом деле превращаются компилятором в обычные внутренние классы.

— Ага. Я даже помню, что у них имена – это числа: 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 – это небольшая плата за то, что компилятор за тебя сгенерирует класс, передаст в него и сохранит там все переменные метода, которые ты хочешь использовать.

— Согласен. Все-таки это крутая штука – анонимные локальные классы.

А если я объявлю внутри метода свой локальный класс и буду в нем использовать переменные метода, компилятор их тоже добавит этому классу?

— Да, добавит в класс и его конструктор.

— Я так и думал.

Комментарии (154)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Сайфер
Уровень 51
11 августа 2025, 12:24
Исходный пример:
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;
        }
    }
}
HISMAN
Уровень 46
1 марта, 20:07
спасибо
Ruslan Gabzalilov
Уровень 27
21 мая, 07:21
Огромное спасибо)
Ioanna Polyak
Уровень 51
8 июля 2025, 17:15
вспомнилось: - "Если будешь плохо учиться, придёт Java, - и съест твой мозг!" 👁😬
arsvasimov Java Developer в Phractal Client
7 июня 2025, 13:06
точно ;}
Дима Мицура
Уровень 46
17 февраля 2025, 00:40
пример кода сжатый на 1 строку - это чтобы стало понятнее?
FolFix
Уровень 38
19 ноября 2024, 13:44
Вроде-бы понятно, но лучше прочитать ещё раз...
Private Joker
Уровень 36
11 июля 2024, 14:54
Из лекции понятно, что что-то там происходит кароч.
Dr.Alexcemen9Врач в Поликлиника в деревн
6 сентября 2024, 05:33
благодарим за ваш комментарий. Ваше мнение очень важно!✍🤡
Igor Okishor
Уровень 41
Expert
24 марта 2024, 00:11
Кое-что стало понятно: объект локального класса может продолжить существовать , когда выполнение программы уже покинет тело метода, где всё это было создано. Одно только мне не понятно (просветите, кто прошарил): если наш локальный класс перестает существовать, когда мы выходим из блока, в котором он создан, как вообще продолжает своё существование экземпляр "стёртого" класса, если больше нигде не описываются его состояние и возможное поведение? Как с этим объектом взаимодействовать?
Long_byte
Уровень 60
27 мая 2024, 14:17
Локальные классы в Java - это классы, которые определяются внутри метода. Они имеют доступ ко всем переменным и параметрам метода, в котором они определены, при условии, что эти переменные и параметры являются `final` или эффективно финальными. Когда метод, содержащий локальный класс, завершает свою работу, код этого класса не "стирается". То есть, байт-код класса остается доступным для использования. Объекты локальных классов могут продолжать существовать и работать после выхода метода благодаря механизму внутреннего хранения. Основные моменты: 1. **Захват контекста**: Локальный класс захватывает (или копирует) значения локальных переменных метода, которые он использует. Эти переменные должны быть `final` или эффективно финальными (то есть, их значение не меняется после инициализации). 2. **Код класса**: После выхода из метода байт-код локального класса сохраняется в области памяти, где он доступен для создания новых объектов этого класса. 3. **Жизненный цикл объектов**: Объекты локального класса могут продолжать существовать даже после выхода из метода, так как они хранят ссылки на копии захваченных переменных и методов.
7 марта 2024, 10:27
«Внутренний класс не может изменить локальную переменную метода, т.к. к тому времени, когда будет исполняться код этого класса, мы уже можем вообще уйти из метода.» в смысле уйти ? Кто-нибудь понял что здесь имеется ввиду ?
28 июля 2025, 06:27
Заметьте, что в задачах на локальные классы метод, где описан локальный класс, возвращает объект этого класса. Это значит, что после выхода из метода, этот объект будет еще "жить", и вызов его метода, реализованного в локальном классе, как раз и потребует исполнения кода локального класса.
7 марта 2024, 08:55
Вообще не интересная тема
Алексей
Уровень 40
Expert
17 января 2024, 17:37
интересная тема