为什么增强型for循环的局部变量必须是局部的?

14 浏览
0 Comments

为什么增强型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 (Iterator iterator = stateList.iterator(); iterator.hasNext(); ) {
    State state = iterator.next();
    // ...
}

与前述情况类似,这个后者的循环可以写成:

State state;
for (Iterator iterator = stateList.iterator(); iterator.hasNext(); ) {
    state = iterator.next();
    // ...
}

同样地,这可以作为(非法的)增强型for循环的功能等效。

在每种情况下,当循环结束时,state的值是完全定义的(尽管可能无用)。而且,就像普通循环一样,使用未定义的裸变量名称的增强型for循环(例如,缺少State state;这一行或超出范围)可以在编译时捕获。那么从语言设计的角度来看,问题出在哪里?为什么语言设计者禁止了这种结构?

0