为什么增强for循环的局部变量必须是局部变量? [英] Why does the local variable of an enhanced for loop have to be local?

查看:230
本文介绍了为什么增强for循环的局部变量必须是局部变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 Java语言规范§14.14 .2 ,对于循环,增强型的变量必须是循环的本地变量。换句话说,这个编译:



$ p $ for(State state:State.values()){
// do

$ / code $ / pre

但这不是: b

 状态; 
for(state:State.values()){
//为每个状态做一些事情
}

JLS没有给出这种语言设计选择的理由。我可以看到为什么类型名称必须存在,如果局部变量被 final 修改或注释,但我不明白为什么一个变量的裸名称声明其他地方是不允许的。有没有人有任何洞察,为什么这个限制是强加的?

编辑

到目前为止,有几个答案似乎暗示了在循环之外发生的事情就是这样设计语言的原因。也许仔细研究一下JLS所说的内容,将会说明为什么我没有发现这种说服力。考虑这个循环,其中 State 是一个枚举:

  for状态:State.values()){
// ...
}



<



<= code> State.values()
是一个数组,因此根据JLS,循环在功能上与以下内容相同: pre> State [] a = State.values();
for(int i = 0; i State state = a [i];
// ...
}

已经写成:

 状态状态; 
State [] a = State.values();
for(int i = 0; i< a.length; i ++){
state = a [i];
// ...
}

从概念上讲, )循环可以被用作上面的循环的第二个增强的的功能等价物(不能编译的循环)。


$ b $同样,如果 stateList 是一个 Iterable< State> (不是一个数组),这个循环:


  for(State state:stateList){
// ...
}

在功能上与以下内容相同:

 <$ c ();();}();}(); 
// ...
}

像以前一样,后一个循环
可以写成:

 状态; 
for(Iterator< state> iterator = stateList.iterator(); iterator.hasNext();){
state = iterator.next();
// ...
}

同样,这个可以已被用作(非法)的功能等价物:

 状态; (state:stateList)


code b

在每种情况下,当循环退出时, state 的值完全定义好(如果也许没用)。同样,正如使用常规循环一样,使用未定义的裸变量名称(例如,行 State state; )来增强 / code>丢失或超出范围)可能会在编译时被捕获。所以从语言设计的角度来看,问题是什么?为什么语言设计者将此构造定义为违法?解决方案一个好处/理由是局部变量不会污染你的代码。让我给出一个正常循环的例子(这只是比喻不是一个确切的例子,所以没有迭代器的使用):

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

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

现在在上面的代码中仔细看看会发现一个潜在的bug。 i 已被错误地用于迭代 j 的循环。



所以增强的循环尝试通过在本地创建变量来安全地玩,从而避免上述问题。

According to the Java Language Specification, § 14.14.2, the variable of an enhanced for loop must be local to the loop. In other words, this compiles:

for (State state : State.values()) {
    // do something for each state
}

but this does not:

State state;
for (state: State.values()) {
    // do something for each state
}

The JLS gives no rationale for this language design choice. I can see why the type name must be present if the local variable is modified by final or by an annotation, but I don't understand why a bare name of a variable declared elsewhere isn't allowed. Does anyone have any insight into why this restriction was imposed?

EDIT

Several answers so far seem to be suggesting that what happens outside the loop is reason for designing the language this way. Perhaps a closer examination of what the JLS says will clarify why I don't find this convincing. Consider this loop, where State is an enum:

for (State state : State.values()) {
    // ...
}

State.values() is an array, so according to the JLS, the loop is functionally identical to:

State[] a = State.values();
for (int i = 0; i < a.length; i++) {
    State state = a[i];
    // ...
}

Now clearly this latter loop could have been written:

State state;
State[] a = State.values();
for (int i = 0; i < a.length; i++) {
    state = a[i];
    // ...
}

Conceptually, this last (perfectly legal) loop could have been used as the functional equivalent of the second enhanced for loop above (the one that does not compile).

Similarly, if stateList is an Iterable<State> (not an array), this loop:

for (State state : stateList) {
    // ...
}

is functionally identical to:

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

Like before, this latter loop could have been written:

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

Again, this could have been used as the functional equivalent of the (illegal):

State state;
for (state : stateList) {
    // ...
}

In each case, when the loop exits, the value of state is perfectly well defined (if, perhaps, useless). Also, just as with the regular loop, an enhanced for loop using a bare variable name that was not defined (e.g., the line State state; was missing or out of scope) could be caught at compile time. So from a language design perspective, what's the problem? Why did the language designers outlaw this construct?

解决方案

One benefit/rationale is local variables dont pollute your code. Let me give a normal loop example (this is just for analogy not an exact one, so no iterator use):

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

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

Now in the above code if look closely you will find a potential bug. i has been mistakenly used in loop which iterates over j.

So enhanced loops try to play safe by creating the variables locally, by which you can avoid above problem.

这篇关于为什么增强for循环的局部变量必须是局部变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆