根据Java语言规范§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
或通过注释修改了局部变量的原因,为什么必须出现类型名称,但是我不明白为什么不允许在其他地方声明的变量的裸名。是否有人对为什么施加此限制有任何见解?
编辑
到目前为止,有几个答案似乎表明,循环之外发生的事情是按这种方式设计语言的原因。也许仔细研究一下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<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();
// ...
}
同样,这可以用作(非法)的功能等效项:
State state;
for (state : stateList) {
// ...
}
在每种情况下,当循环退出时,的值state
都定义得很好(如果没有用的话)。同样,与常规循环一样,for
使用未定义的裸变量名称(例如,行State state;
丢失或超出范围)的增强型循环可能会在编译时捕获。那么从语言设计的角度来看,这是什么问题呢?语言设计者为何将这种结构定为非法?
一种好处/理由是局部变量不会污染您的代码。让我给出一个普通的循环示例(出于类比,这不是一个确切的例子,因此没有迭代器使用):
int i;
for(i=0;i<10;i++)
do...something
int j;
for(j=0; i<10; j++)
do...something
现在,在上面的代码中,如果仔细观察,您将发现一个潜在的错误。i
已被错误地用于循环遍历的循环中j
。
因此,增强型循环尝试通过在本地创建变量来确保安全,从而可以避免上述问题。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句