С Новым годом! Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.64/25: Рейтинг темы: голосов - 25, средняя оценка - 4.64
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137

Почему локальные переменные методов нельзя изменять в анонимных классах?

20.03.2016, 23:28. Показов 5512. Ответов 26
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Почему Java защищает от изменения локальные переменные методов, когда пытаешься их изменить в анонимном внутреннем классе? Она требует, чтобы они были финальными. То же самое с лямбда - выражениями. Я гуглил этот вопрос, но что-то как-то не совсем понял
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
20.03.2016, 23:28
Ответы с готовыми решениями:

Почему в некоторых классах нет встроенных методов BindingList'a
Всем привет! Прошу огромной помощи. Либо я совсем сошел с ума, либо в VS вселился сатана. Есть класс, в нем приватно объявлен...

Почему в switch нельзя определять переменные?
int main() { setlocale(LC_ALL, "Russian"); int n; std::cout << "Введите число: "; std::cin >> n; switch...

Почему нельзя использовать глобальные переменные
Здравствуйте, собственно вышел сиз данным вопросом в гугл и на стаке нашел такой ответ: 1)Глобальные переменные в большинстве случаев...

26
Эксперт Java
 Аватар для KEKCoGEN
2399 / 2224 / 565
Регистрация: 28.12.2010
Сообщений: 8,672
21.03.2016, 09:37
danek130995, насколько я знаю, если эти переменные не будут финальными, они умрут после завершения метода и когда сработает ваш метод анонимного класса, их уже не будет.
1
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
21.03.2016, 11:06  [ТС]
KEKCoGEN, а почему они умирают? Ведь анонимный класс находится внутри метода
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
21.03.2016, 21:21
Переменная. Переменная перестанет существовать после выхода из функции.
Компилятор подставит на момент создания анонимного класса значение из переменной функции.
А присвоение окажется "в никуда".
1
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
21.03.2016, 21:45  [ТС]
lemegeton, не понял. Вы имеете ввиду, что когда создаётся анонимный класс, производится выход из метода? И перестают существовать локальные переменные? А почему же тогда финальные не перестают существовать? Под функцией Вы имеете ввиду метод? А если анонимный класс создаётся не в конце метода? После его выполнения они опять начинают существовать? Я не совсем понимаю, не могли бы вы пожалуйста объяснить подробнее
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
21.03.2016, 23:11
Лучший ответ Сообщение было отмечено danek130995 как решение

Решение

Представим, что было бы разрешено.
Java
1
2
3
4
int s = 10;
Runnable r = () -> { System.out.println(s); };
s = 20;
r.run();//Какое значение выведется тут в sysout? 10 или 20?
Обязательство замыкать всегда только final переменные избавляет от данного вопроса, в принципе. Это раз.

Во-вторых, если бы такое было бы разрешено (как в C# например), то это обязало бы компилятор, генерировать дополнительный класс-обёртку, чтобы при изменение переменной, анонимный класс видел бы эти изменения. А это дополнительный overhead.
1
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,764
22.03.2016, 08:06
Цитата Сообщение от turbanoff Посмотреть сообщение
r.run();//Какое значение выведется тут в sysout? 10 или 20?
20, конечно.

Цитата Сообщение от turbanoff Посмотреть сообщение
Обязательство замыкать всегда только final переменные избавляет от данного вопроса, в принципе. Это раз.
Просто лексические окружения в Java не являются полноценными объектами/структурами и не управляются сборщиком мусора. В отличие от всех(или, по крайне мере подавляющего большинства) других языков, поддерживающих замыкания.

Цитата Сообщение от turbanoff Посмотреть сообщение
то это обязало бы компилятор, генерировать дополнительный класс-обёртку, чтобы при изменение переменной, анонимный класс видел бы эти изменения.
Не обязало бы, если бы рантайм умел сохранять окружения полностью, а не только this внешних классов. Но обратная совместимость, да…

Добавлено через 4 минуты
BTW, если не ошибаюсь, в Java 9 эту возможность собираются реализовать.
1
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
22.03.2016, 11:04
Лучший ответ Сообщение было отмечено danek130995 как решение

Решение

Поясню мысль примером.
Вот от чего защищается компилятор:
Java
1
2
3
4
5
6
7
8
9
10
11
12
        public Runnable get() {
            int x = 0; // эта переменная имеет смысл только в контексте этой функции
            // это замыкание может оказаться выполнено в любой момент времени
            // но явно после того, как функция get() завершится
            return new Runnable() { 
                @Override
                public void run() {
                    x = x + 1;
                    System.out.println(x);
                }
            };
        }
После выхода из функции переменная x, как любая локальная переменная, перестанет существовать.
А возвращаемое замыкание будет выполнено лишь после этого прискорбного факта.
И чему тогда присваивать?

Приблизительный аналог из С++ это возвращения ссылки на локальную переменную.

Да, гораздо чаще нам нужно выполнить функцию в том же контексте:
Java
1
2
3
4
5
6
7
8
9
10
11
        public int get() {
            int x = 0;
            new Runnable() {
                @Override
                public void run() {
                    x = x + 1;
                    System.out.println(x);
                }
            }.run();
            return x;
        }
... и казалось бы, ну тут-то можно же... Но компилятор пока не настолько умён.

Обходить коряво -- созданием массива из одного элемента и работой с ним.
Java
1
2
3
4
5
6
7
8
9
10
11
        public int get() {
            int x[] = {0};
            new Runnable() {
                @Override
                public void run() {
                    x[0] = x[0] + 1;
                    System.out.println(x[0]);
                }
            }.run();
            return x[0];
        }
или
Java
1
2
3
4
5
6
7
8
9
10
        public Runnable get() {
            int x[] = {0};
            return new Runnable() {
                @Override
                public void run() {
                    x[0] = x[0] + 1;
                    System.out.println(x[0]);
                }
            };
        }
Почему это работает? Потому что переменная на стеке, тобишь "x" исчезнет, но объект массива будет создан в общей куче и с ним всё будет хорошо.
1
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
22.03.2016, 18:00
Цитата Сообщение от korvin_ Посмотреть сообщение
BTW, если не ошибаюсь, в Java 9 эту возможность собираются реализовать.
нет, ничего такого не предвидется.
1
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
22.03.2016, 19:12  [ТС]
lemegeton, turbanoff что такое здесь замыкание? Почему Вы употребляете это слово?

Добавлено через 5 минут
lemegeton,
Почему это работает? Потому что переменная на стеке, тобишь "x" исчезнет, но объект массива будет создан в общей куче и с ним всё будет хорошо.
- вот это для меня вообще дико прозвучало. Интересное дело, x исчезнет, а массив в куче останется. А как же сборщик мусора
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,764
22.03.2016, 20:49
Цитата Сообщение от danek130995 Посмотреть сообщение
что такое здесь замыкание? Почему Вы употребляете это слово?
https://en.wikipedia.org/wiki/... ogramming)
1
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
22.03.2016, 22:54
Цитата Сообщение от danek130995 Посмотреть сообщение
- вот это для меня вообще дико прозвучало. Интересное дело, x исчезнет, а массив в куче останется. А как же сборщик мусора
^____^
Внутри функций переменные создаются на стеке. А объекты -- в куче.
Переменные исчезают, а объекты -- не сразу. Сборщик мусора их соберёт, когда посчитает нужным. Если на них ссылок не будет. А тут будет ссылка -- внутри замыкания. Объект не исчезнет.

Java
1
2
int x = 1; // переменная, как и её содержимое, исчезнет сразу после выхода из функции
String a = new String("string"); // переменная a исчезнет сразу после выхода из функции, но ОБЪЕКТ типа String будет создан в куче и может не исчезнуть по окончанию, если его ссылка будет куда-нибудь скопирована.
1
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
22.03.2016, 23:23  [ТС]
lemegeton, да, но если X исчезнет, как же мы обращаемся к X[0]? Понятно, что объект жив, но к нему идёт обращение по ссылке через X, но ведь его не будет же?

Добавлено через 2 минуты
korvin_, написано, что Википедия не имеет статьи для closure. Я слышал про closure на одном из предметов, там это было показано на примере конечного автомата для множества состояний. А тут как бы его увидеть? Что вы имеете ввиду под closure в java?
0
1123 / 794 / 219
Регистрация: 15.08.2010
Сообщений: 2,185
22.03.2016, 23:29
Цитата Сообщение от danek130995 Посмотреть сообщение
что Википедия не имеет статьи для closure
скобочку дорисуйте в адресе
0
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
23.03.2016, 11:21  [ТС]
КОП, уже заработало)

Добавлено через 12 минут
lemegeton, Вы имеете ввиду, что если x объявлен так: int x, то он исчезнет, а если так int x[] = {0}, то объект будет доступен по ссылке x[0]?
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,764
23.03.2016, 20:34
Цитата Сообщение от danek130995 Посмотреть сообщение
то объект будет доступен по ссылке x[0]?
Объект массив будет доступен по ссылке x.
1
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
23.03.2016, 22:51
Различайте переменную и объект.
Переменная создается на стеке и исчезает по выходу из функции.
Объект создается в общей памяти и исчезает только когда сборщик мусора так решит.

Допустим, внутри функции есть объявление:
Object s = new Object();
s -- переменная -- исчезнет, а объект, созданный new Object() удалится только тогда, когда на него пропадут все ссылки.
1
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
24.03.2016, 18:59  [ТС]
lemegeton, да, это понятно, но, если s(переменная,ссылка) - исчезнет, тогда исчезнет и объект? Я это к тому, что
Цитата Сообщение от korvin_ Посмотреть сообщение
Объект массив будет доступен по ссылке x.
Если исчезнет переменная x, которая является в данном контексте и единственной ссылкой, тогда должен и объект исчезнуть, но почему тогда korvin_ говорит, что он будет доступен по ссылке x? Если бы была другая какая-нибудь ссылка еще на него, тогда понятно.
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
24.03.2016, 20:08
Значение переменной будет скопировано компилятором на момент обращения.
1
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
24.03.2016, 21:38  [ТС]
lemegeton,оно будет скопировано в анонимный класс?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
24.03.2016, 21:38
Помогаю со студенческими работами здесь

Почему нельзя подставлять переменные в выражения #if #else?
Почему код работает, не должен же, потому что выражение стоящее после #if вычисляется на этапе компиляции, переменные подставлять нельзя?? ...

Использование анонимных методов
Анонимные методы используются, когда нужно создать метод для обработки какого-то события и больше этот метод нигде использоваться не будет....

Почему нельзя использовать в операторе case переменные, которые определены как #define
Я не понимаю, почему Visual Studio ругается на строку с case в коде. Вроде все правильно. Если там написать напрямую цифру, тогда все...

Дебаггинг анонимных методов и лямбда-выражений
Добрый вечер. Написал свой первый более-менее серьезный и полезный проект на C# и уперся в дебаггинг. По опыту микроконтроллеров знаю, что...

Использование анонимных методов внутри цикла foreach
Добрый день, у меня возникла любопытная ситуация, поведение которой я не знаю как объяснить. В общим есть такая строчка кода. ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru