根据Java 语言规范,第 14.14.2 节 http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.14.2,增强的变量for
循环必须是循环的本地循环。换句话说,这可以编译:
for (State state : State.values()) {
// do something for each state
}
但这并没有:
State state;
for (state: State.values()) {
// do something for each state
}
JLS 没有给出这种语言设计选择的理由。我可以明白为什么如果局部变量被修改,类型名称必须存在final
或通过注释,但我不明白为什么不允许在其他地方声明的变量的裸名称。有谁知道为什么要施加此限制?
EDIT
到目前为止,几个答案似乎表明循环之外发生的事情是以这种方式设计语言的原因。也许仔细研究一下 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
is an Iterable<State>
(不是数组),这个循环:
for (State state : stateList) {
// ...
}
功能上与以下相同:
for (Iterator<State> iterator = stateList.iterator(); iterator.hasNext(); ) {
State state = iterator.next();
// ...
}
和之前一样,后一个循环
可以写成:
State state;
for (Iterator<State> iterator = stateList.iterator(); iterator.hasNext(); ) {
state = iterator.next();
// ...
}
再说一遍,这个could已被用作(非法)的功能等同物:
State state;
for (state : stateList) {
// ...
}
在每种情况下,当循环退出时,值state
是完全明确定义的(如果,也许,无用的话)。此外,就像常规循环一样,增强型for
使用未定义的裸变量名进行循环(例如,行State state;
丢失或超出范围)可以在编译时捕获。那么从语言设计的角度来看,问题出在哪里呢?为什么语言设计者禁止这种构造?