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

2022-09-01 08:58:59

根据 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

类似地,如果 是一个(不是数组),则此循环:stateListIterable<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) {
    // ...
}

在每种情况下,当循环退出时,的值是完全定义的(如果,也许,无用)。此外,就像常规循环一样,可以在编译时捕获使用未定义的裸变量名称(例如,行丢失或超出范围)的增强循环。那么从语言设计的角度来看,问题出在哪里呢?为什么语言设计者取缔了这个结构?stateforState state;


答案 1

看看 for-each 循环在内部是如何工作的,请参阅 Java 'for each' 循环是如何工作的?

for(Iterator<String> i = someList.iterator(); i.hasNext(); ) {
String item = i.next();
System.out.println(item);
}

每次它声明 String 变量项时。因此,在你的情况下,它基本上做

State state;
\\and inside
State state = i.next();

这显然行不通。现在在实现内部,他们只能做

item = i.next();

但是,您始终必须在每个项目之外定义该项目,这在大多数时候都是痛苦的。


答案 2

一个好处/理由是局部变量不会污染你的代码。让我举一个普通的循环示例(这只是一个类比,而不是一个精确的类比,所以没有迭代器使用):

int i;
for(i=0;i<10;i++)
  do...something

int j;
for(j=0; i<10; j++)
  do...something

现在在上面的代码中,如果仔细观察,你会发现一个潜在的错误。 在循环中被错误地使用,该循环循环访问 了 。ij

因此,增强的循环试图通过在本地创建变量来确保安全,通过它可以避免上述问题。