所以,这就是我的理解:Java 不支持闭包,因此它会将变量从包含范围复制到嵌套范围中,以便以后可以使用。因为这是一个副本,所以无法同步原始和副本,并且变量被强制为最终变量,因此开发人员无法更改它并期望它被更新。这种理解部分来自这些答案
这将我们带到了这段代码的工作中:
public class SimpleClosure {
public static void main(String[] args) {
new SimpleClosure().doStuff();
}
public void doStuff() {
final int number = 3;
new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Integer.toString(number));
}
}.start();
}
}
很好。现在,问题是,最终修饰符只会阻止我更改变量指向的对象,但我可以毫无问题地更改对象。如果进行了“复制”,则不应反映对对象内容的更改。因此,问题是,为什么下面的代码有效?
import java.util.HashMap;
import java.util.Map;
public class StretchingClosure {
public static void main(String[] args) {
new StretchingClosure().doStuff();
}
public void doStuff() {
final Map<String, String> map = new HashMap<String, String>();
map.put("animal", "cat");
new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(map.get("animal")); // Outputs dog See (1)
}
}.start();
map.put("animal", "dog");
}
}
不用说,我遗漏了一些东西,或者我过度简化了编译器处理这些情况的方式。有人可以请教我吗?
(1):正如@trashgod 所指出的,在大多数平台上大部分时间输出都是正确的,但由于缺乏同步,不能保证。这对于示例来说已经足够了,但通常是不好的做法。