Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 851
Ted Hopp Avatar asked Nov 20 '11 20:11

Ted Hopp


1 Answers

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.

like image 176
Adithya Surampudi Avatar answered Oct 17 '22 20:10

Adithya Surampudi