我知道以下示例中使用的foreach循环无法编译。但有人知道为什么不允许在foreach循环声明中使用字段吗?
public class Foo {
private Object obj;
public void run(List<Object> objects) {
for (obj : objects) {
process();
}
}
private void process() {
// do something with obj
}
}
答案 0 :(得分:7)
可能是因为它
答案 1 :(得分:2)
分配给foreach循环中的字段通常没有意义。 foreach循环中对象的范围只是循环的一次迭代,而字段的范围是对象的生命周期。
你应该把每个对象作为参数传递给process()
...你不会通过将引用存储为字段来获得任何东西。另外,如果您真的想要,可以使用this.obj = obj
手动分配到某个字段。
答案 2 :(得分:1)
我希望有几个原因,但它可能只是为了防止程序员错误。
令人困惑的一件事是“循环执行后obj的价值是什么”?与标准for循环不同,增强的for-each循环并不试图保证它自己的机制。
另一件事是实例字段代表对象的状态。通过在for-each循环中使用实例字段,你要说的是对象可以从一个状态变为一个或多个中间状态,然后在单个操作过程中最终变为状态 。这只是糟糕的设计,值得预防。
为什么不将obj作为参数传递给process()
?
答案 3 :(得分:1)
运行for循环之前obj
应该有什么值,循环运行后应该有什么值?这会令人困惑。
答案 4 :(得分:1)
2004年这个问题上有一个bug report。它被拒绝,回复很有意思:
通过强制循环变量在循环内声明,采用了某种“安全优先”方法(参见JLS 14.14.2中的翻译)。首先,不存在意外地破坏封闭范围中的变量的危险。其次,如果变量由循环体传递给其他线程,则每次迭代使用一个新的循环变量可以避免并发问题。第三,编译器可以通过将循环变量声明为“final”来进行优化。第四,如果封闭范围中的变量被重用作循环变量,并且程序员认为循环遍历整个集合,那么他们可能期望能够在迭代之后通过循环观察集合中的最后一个元素变量。但它不一定是指最后一个元素,例如如果循环中断了。