В интернете я прочитала, что IntelliJ IDEA по умолчанию подчеркивает переназначенные локальные переменные и переназначенные параметры. И что если переменная/параметр подчеркнута, мы знаем, что не можем использовать ее в лямбде/анонимном классе напрямую. Но мне это особо ничего не прояснило :с
То есть все переменные, которые меняются, будут подчеркиваться? И мы их не можем использовать в анонимном классе и функции? Но почему нет?
Ada
46 уровень
Почему IDEA подчеркивает некоторые переменные?
Решен
Комментарии (8)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Павел Безумный учёный Expert
26 апреля 2022, 22:54решение
Анонимный класс не может изменять локальные переменные и параметры метода, в контексте которого он находится. При этом сами значения локальных переменных и параметров можно использовать в анонимном классе, но при условии, что они не будут изменяться. Это ограничение связано с временем жизни локальных переменных, которое может оказаться меньше времени жизни объекта анонимного класса, использующего эти переменные.
Рассмотрим пример:
+2
Павел Безумный учёный Expert
26 апреля 2022, 22:54
Когда мы создаём объект Example, в конструкторе вызывается метод method(). В теле метода method() создаётся объект анонимного класса, реализующего интерфейс Runnable. Ссылка на созданный объект присваивается полю экземпляра Example. То есть, объект runnable будет существовать всё время, пока существует содержащий его экземпляр Example.
Переменные b и c - это локальные переменные метода method(), их существование ограничено контекстом этого метода (то есть когда метод завершается, эти две переменные пропадают). Именно по этой причине и происходит главное противоречие: когда на созданном ранее объекте runnable вызывается метод run() (в конструкторе), получается, что он не может быть выполнен! Ведь переменных b и c попросту не существует, поскольку контекст метода method() не был создан (он создаётся только на время работы метода). Другими словами, объект анонимного класса runnable используется в отрыве от контекста метода method(), что нарушает принцип инкапсуляции, лежащий в основе языка Java.
+2
Павел Безумный учёный Expert
26 апреля 2022, 22:55
Строго говоря, переменные b и c всё же сохраняются в объекте анонимного класса. Но это происходит лишь один раз при его создании: происходит так называемый "захват" переменной. При "захвате" локальная переменная копируется внутрь анонимного класса, и все дальнейшие операции происходят именно с этой копией, не затрагивая "оригинал". По этой причине изменение "захваченной" переменной не имеет смысла - доступ извне к ней получить нельзя, и её изменённое значение никак не повлияет на локальную переменную (оригинал), а только собьёт с толку разработчика. Именно с этими "захваченными" копиями переменных b и c будет работать метод run(), когда он будет вызван в конструкторе (строка 7).
Чтобы избежать описанных проблем и противоречий, авторами языка было введено ограничение: локальные переменные, используемые в анонимном классе, должны быть неизменяемыми (final) или, по крайней мере, разработчик не должен пытаться их изменить (effectively final, то есть не объявленная как final, но считающаяся таковой). Такие переменные действительно выделяются в IDEA подчёркиванием - видимо, в качестве напоминания о существующем ограничении.
Строки 16 и 17 не скомпилируются как раз по этой причине: компилятор считает их effectively final, но это ограничение игнорируется и производится попытка изменения значений этих переменных.
+2
Павел Безумный учёный Expert
26 апреля 2022, 22:55
В то же время описанные ограничения не затрагивают поля класса. К примеру, значение поля a вполне может быть изменено внутри анонимного класса (см. строку 15). Это логически верно, ведь поле a "живёт" столько же, сколько и сам экземпляр Example, то есть к нему всегда может быть получен доступ из объекта анонимного класса runnable.
Подробнее можно почитать здесь и здесь.
+2
Ada
29 апреля 2022, 11:08
Большое спасибо за такой подробный ответ! Пока не все смогла понять, буду возвращаться к нему по мере прохождения курса
0
Павел Безумный учёный Expert
29 апреля 2022, 15:15полезный
Не переживайте, если на данный момент нет полной ясности в этом вопросе. Эта тонкость языка станет для Вас очевидной по мере получения практического опыта в области использования лямбда-выражений и анонимных классов. Главное, что зерно упало в почву, и вскоре оно даст свои плоды!
+1
Ada
30 апреля 2022, 14:41
Большое спасибо, Павел!
0
Павел Безумный учёный Expert
30 апреля 2022, 15:31
На здоровье)
+1