Why does the local variable of an enhanced for loop have to be local? [duplicate]

£可爱£侵袭症+ 提交于 2019-12-04 08:50:00

问题


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?


回答1:


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.




回答2:


Look at how the for-each loop internally works, see How does the Java 'for each' loop work?

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

Each time it declares the String variable item. Hence in your case its doing essentially

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

which obviously wont work. Now inside the implementation, they it could rather only do

item = i.next();

but then you always have to define that item outside for-each, which would be pain majority of time.




回答3:


A lot of decisions in Java are more based on the concept of why "Wouldn't" you remove x. Why on earth allow your code to be confused by moving the scope outside the loop? If you really needed access to the last element afterwards there are cleaner ways.

I suppose some may argue one way or another as to protecting programmers from themselves, I look at it more as Java protects me from people who like to take advantage of things like this.

It's not really a great hobby language, it is a great team development language where the point is to make it as easy as possible for the next guy to understand your code.

For instance, I saw in a comment above that many people break out of a for loop at a certain point with a value. How clear is that when you are scanning through code trying to find a bug? It's people using neat tricks like this that I really want to be protected from, not myself.

If you wish to execute some code mid-loop, put it in a method and call it from within the loop.

The lack of cute tricks often makes me re-think my code and work a little harder--but the results are always more readable/maintainable.

If you are just a single programmer (Not on a team) I'd advise against Java, It doesn't do neat tricks and you won't see cool yearly feature updates--and it is fairly slow to program in (It moves a lot of time catching and fixing bugs into time spent coding, frustrating people with it's strict rules (One of the biggest advantages of the language IMO)

If you want something javaish try Scala instead. If you are "Forced" to learn it because of a classroom decision then you might want to attempt to appreciate it from the "team" point of view and with the mindset that you won't be forced to use it in the future.




回答4:


They might have wanted to remove a possible difference in semantics between the simple for and the enhanced for.

If you had, say, a regular for loop:

int i;
for (i=0; i<4; i++)
    ;

then if you let the loop execute normally, you get that i==4 after the loop, which is not valid for the iteration variable.

What then, if you could have:

int i;
for (i : myArray)
    ;

I suppose from an implementation standpoint, it would be easiest if at the end i were equal to the last element in the array. But should it behave like that or should there be some invalid value, and if so, what could that be? What if you break out of the last iteration?

Another possibility is that it makes it more clear what that loop is about and what the element type of the collection is. By contrast, the simple for is a "legacy" construct in some sense, so they couldn't have applied a similar logic without "breaking" it or limiting its flexibility.

I'm obviously speculating, and it could turn out to have just been a random design choice.




回答5:


Maybe because in this way, it guarantees that state will be empty and has no initial value assigned to it.



来源:https://stackoverflow.com/questions/8204341/why-does-the-local-variable-of-an-enhanced-for-loop-have-to-be-local

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!