Насколько я понимаю, в Java нет истинных замыканий. Вы можете передать функцию, сопровождая их классом; однако он не только многословен, но и (из-за модели памяти Java) любые ссылки в анонимном классе на переменные, определенные в среде, в которой он был создан, передаются как copy . Язык побуждает нас помнить об этом, позволяя анонимным классам ссылаться только на final
переменных.
Что приводит меня к этому фрагменту кода, который я нашел в Bloch's Effective Java :
import java.util.concurrent.*;
public class StopThread {
private static boolean stopRequested;
public static void main(String[] args)
throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested)
i++;
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
Во-первых, я ожидал, что компилятор будет жаловаться, потому что stopRequested
не является окончательным, и я ссылаюсь на него внутри анонимного класса. Мой компилятор не жаловался.
Во-вторых, я ожидал, что программа будет зацикливаться вечно, поскольку Java не поддерживает замыкания, и если анонимный класс действительно ссылается на фактическую переменную stopRequested
из среды, в которой он был создан (а не является простой копией) тогда кажется, что у нас есть закрытие здесь. Джошуа Блох также сказал, что программа навсегда зацикливается на его компьютере. Но моя работает около секунды и выходит.
Какую часть модели памяти я неправильно понимаю?