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

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

20.03.2016, 23:28. Показов 5514. Ответов 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
Ответ Создать тему
Новые блоги и статьи
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Old Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
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. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru