К каким переменным есть доступ у лямбда-выражений?
Лямбда-выражение может обращаться к переменным из внешней области видимости, но с ограничениями. Доступны три категории переменных: effectively final локальные переменные, поля экземпляра класса и статические переменные.
Правила доступа
| Категория переменной | Доступ из лямбды | Можно ли изменять? |
|---|---|---|
| Локальная effectively final | Да (чтение) | Нет |
| Поле экземпляра | Да (чтение и запись) | Да |
| Статическая переменная | Да (чтение и запись) | Да |
default-метод функционального интерфейса |
Нет | – |
Effectively final означает, что переменная не обязана быть помечена final, но после инициализации её значение не должно изменяться. Это ограничение существует потому, что лямбда захватывает копию значения локальной переменной, а не ссылку на неё. Если бы переменная менялась, копия стала бы некорректной — поэтому компилятор запрещает модификацию.
Поля класса и статические переменные хранятся в куче (heap), а не на стеке, поэтому лямбда может безопасно читать и изменять их значения.
На собеседовании: часто просят объяснить, почему нельзя модифицировать локальную переменную внутри лямбды. Ключевой аргумент — лямбда захватывает копию значения, а не ссылку на переменную стека, поэтому изменение оригинала привело бы к рассинхронизации.