为什么增强型for循环的局部变量必须是局部的?
为什么增强型for循环的局部变量必须是局部的?
根据Java语言规范第14.14.2节,增强型for
循环的变量必须是循环内的局部变量。换句话说,下面的代码可以编译通过:
for (State state : State.values()) { // 对每个state做一些操作 }
但下面的代码不行:
State state; for (state: State.values()) { // 对每个state做一些操作 }
关于这种语言设计选择,JLS没有给出解释。我可以理解如果局部变量被final
或注解修改,为什么要求类型名称存在,但我不明白为什么不允许使用在其他地方声明的变量的裸名。有人能解释一下为什么有这个限制吗?
编辑
到目前为止,有几个答案似乎在暗示这种设计方式的原因是循环外发生的事情。也许进一步审查JLS的内容将澄清为什么我不认为这样的解释令人信服。考虑以下循环,其中State
是一个枚举:
for (State state : State.values()) { // ... }
State.values()
是一个数组,所以根据JLS,这个循环在功能上与下面的循环是相同的:
State[] a = State.values(); for (int i = 0; i < a.length; i++) { State state = a[i]; // ... }
显然,后者的循环可以写成:
State state; State[] a = State.values(); for (int i = 0; i < a.length; i++) { state = a[i]; // ... }
从概念上讲,这个(完全合法的)循环可以作为第二个增强型for
循环的功能等效(不可编译的那个)。
同样地,如果stateList
是一个Iterable
(而不是数组),这个循环:
for (State state : stateList) { // ... }
在功能上等同于:
for (Iteratoriterator = stateList.iterator(); iterator.hasNext(); ) { State state = iterator.next(); // ... }
与前述情况类似,这个后者的循环可以写成:
State state; for (Iteratoriterator = stateList.iterator(); iterator.hasNext(); ) { state = iterator.next(); // ... }
同样地,这可以作为(非法的)增强型for
循环的功能等效。
在每种情况下,当循环结束时,state
的值是完全定义的(尽管可能无用)。而且,就像普通循环一样,使用未定义的裸变量名称的增强型for
循环(例如,缺少State state;
这一行或超出范围)可以在编译时捕获。那么从语言设计的角度来看,问题出在哪里?为什么语言设计者禁止了这种结构?