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

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

Java Multithreading
4 уровень , 7 лекция
Открыта
Что происходит на самом деле (Во что превращаются классы компилятором) - 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 – это небольшая плата за то, что компилятор за тебя сгенерирует класс, передаст в него и сохранит там все переменные метода, которые ты хочешь использовать.

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

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

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

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

Комментарии (152)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Скиталец Уровень 51
11 августа 2025
Исходный пример:

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;
        }
    }
}
Ioanna Polyak Уровень 31
8 июля 2025
вспомнилось: - "Если будешь плохо учиться, придёт Java, - и съест твой мозг!" 👁😬
arsvasimov Уровень 51
7 июня 2025
точно ;}
Дима Мицура Уровень 46
17 февраля 2025
пример кода сжатый на 1 строку - это чтобы стало понятнее?
FolFix Уровень 38
19 ноября 2024
Вроде-бы понятно, но лучше прочитать ещё раз...
Private Joker Уровень 36
11 июля 2024
Из лекции понятно, что что-то там происходит кароч.
Dr.Alexcemen9 Уровень 51
6 сентября 2024
благодарим за ваш комментарий. Ваше мнение очень важно!✍🤡
Igor Okishor Уровень 41 Expert
24 марта 2024
Кое-что стало понятно: объект локального класса может продолжить существовать , когда выполнение программы уже покинет тело метода, где всё это было создано. Одно только мне не понятно (просветите, кто прошарил): если наш локальный класс перестает существовать, когда мы выходим из блока, в котором он создан, как вообще продолжает своё существование экземпляр "стёртого" класса, если больше нигде не описываются его состояние и возможное поведение? Как с этим объектом взаимодействовать?
Long_byte Уровень 43
27 мая 2024
Локальные классы в Java - это классы, которые определяются внутри метода. Они имеют доступ ко всем переменным и параметрам метода, в котором они определены, при условии, что эти переменные и параметры являются `final` или эффективно финальными. Когда метод, содержащий локальный класс, завершает свою работу, код этого класса не "стирается". То есть, байт-код класса остается доступным для использования. Объекты локальных классов могут продолжать существовать и работать после выхода метода благодаря механизму внутреннего хранения. Основные моменты: 1. **Захват контекста**: Локальный класс захватывает (или копирует) значения локальных переменных метода, которые он использует. Эти переменные должны быть `final` или эффективно финальными (то есть, их значение не меняется после инициализации). 2. **Код класса**: После выхода из метода байт-код локального класса сохраняется в области памяти, где он доступен для создания новых объектов этого класса. 3. **Жизненный цикл объектов**: Объекты локального класса могут продолжать существовать даже после выхода из метода, так как они хранят ссылки на копии захваченных переменных и методов.
7 марта 2024
«Внутренний класс не может изменить локальную переменную метода, т.к. к тому времени, когда будет исполняться код этого класса, мы уже можем вообще уйти из метода.» в смысле уйти ? Кто-нибудь понял что здесь имеется ввиду ?
28 июля 2025
Заметьте, что в задачах на локальные классы метод, где описан локальный класс, возвращает объект этого класса. Это значит, что после выхода из метода, этот объект будет еще "жить", и вызов его метода, реализованного в локальном классе, как раз и потребует исполнения кода локального класса.
7 марта 2024
Вообще не интересная тема
Алексей Уровень 40 Expert
17 января 2024
интересная тема