Как в лямбде изменить внешнюю локальную переменную?
Изменить локальную переменную, в ламбде, стандартными методами невозможно, потому, что локальная переменная должны быть effectively final, то есть не должна изменяться после объявления.
Это сделано потому что локальная переменная помещается в стек, поэтому её время жизни ограничено скоупом. Однако экземпляр лямбды, который захватил данную переменную, может передать её наружу и использовать в другом потоке или после окончания работы метода.
Для того, чтобы решить данную проблему в лямбда-выражение помещается копия требуемой локальной переменной, которая независима от оригинала. Но в таком случае копия и локальный оригинал будут разными, независящими друг от друга переменными, а это может привести к сложностям, из-за возможности использования неактуальных, устаревших значений. Чтобы значение было всегда актуально оно не должно меняться.
Чтобы изменить локальную переменную нужно отправить её в кучу. Чтобы это сделать, можно использовать обёртку, например, одноэлементный массив или класс с нужной переменной. Однако это не решает проблему с актуальностью. Поэтому, при использовании многопоточности, рекомендуется уделить внимание синхронизации работы потоков с данной переменной.
void doLater(Runnable r){
new Thread(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {}
}).start();
}
void main() {
int i = 0;
doLater(() -> {
// Ошибка - к этому моменту переменная может быть 0, 1, или перестать существовать.
i += 42;
});
i++; // Было бы здесь 43 или 1 - неизвестно.
}
void hackO {
int[] i = {0};
doLater(() -> {
// Теперь это компилируется, но поведение непредсказуемо – опасно
i[0] += 42;
});
i[0]++;
}
Учитесь в сообществе
AI Sprints — обучение профессиям с ИИ
Peer review и код от других студентов. Код-ревью от менторов. Учитесь не в одиночку, а в команде
- Peer review: проверяйте код других и получайте фидбек на свой — учитесь видеть ошибки
- Сообщество: чаты, обсуждения, помощь друг другу — не застрянете в одиночку
- Менторы: код-ревью от практикующих разработчиков на сложные задачи
AI Challenge — собери чат-бота за 5 дней
Бесплатный марафон по AI-инжинирингу. Cursor + OpenAI, 60 минут в день — без опыта в программировании. К пятнице у вас будет рабочий чат-бот с памятью в браузере.
- Практика с первого дня, без теории «в стол»
- Готовый проект в портфолио к концу недели
- Старт в любой день — учитесь в своём темпе