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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With