tags:

views:

89

answers:

4

I know that the foreach loop used in the following example doesn't compile. But does anybody know why using a field in a foreach loop declaration isn't allowed?

public class Foo {
    private Object obj;

    public void run(List<Object> objects) {
        for (obj : objects) {
            process();
        }
    }

    private void process() {
        // do something with obj
    }
}
+2  A: 

It generally doesn't make sense to assign to a field in a foreach loop. The scope of an object in a foreach loop is just the one iteration of the loop, whereas the scope of a field is the lifetime of the object.

You should really just pass each object as an argument to process()... you wouldn't be gaining anything by storing the reference as a field. Plus, if you really really want to you can just manually assign to a field using this.obj = obj.

ColinD
I agree that fields describe the state of an object. However, if an instance of the class only lives during a request in a web application, the use of field instead of a local variable is perfectly fine.
kraftan
@kraftan The thing is, the loop itself is still local to a single method call. As such, the variable used in the loop should should be local as well. Minimizing the scope of things (including variables) is good design, and given the many, many potential problems this would have the potential to introduce (there would be horrible thread safety issues that could be avoided if you didn't use the field) they wisely chose to not allow such a thing. I doubt it was even considered.
ColinD
@ColinD I agree. Not allow such a thing in general is definitely wise.
kraftan
+6  A: 

Probably because it

  • limits the scope of the loop variable (thus making the code clearer, and avoiding possible subtle bugs), and
  • simplifies parsing for the compiler.
Péter Török
I wonder if designers were also thinking of future expansion of the modified for loop to run parallel executions of the body for different values of the loop variable. If the variable existed outside of the loop, it would be difficult to add this feature without implementing a third type of for loop.
Rich
@Rich: that would be difficult to fit within current semantics anyway, since you are currently guaranteed that the order of the elements is the same as the order of the collection's iterator. I think parallelizing would either break that or be useless via oversynchronization.
Mark Peters
@Mark, that makes sense given the guarantee of the order of element visit. I've always been uneasy about the order of the loop. Thanks for lifting a weight off my shoulders.
Rich
+1  A: 

I expect there are a few reasons, but it probably just comes down to preventing programmer error.

One thing that would be confusing is "what would be the value of obj after the loop had executed"? Unlike the standard for-loop, the enhanced for-each loop isn't trying to make guarantees about its own mechanics.

Another thing is that instance fields represent an object's state. What you'd be saying by using an instance field in a for-each loop is that the object could changes from one state, then to one or many intermediate states, then to final a state during the course of a single operation. That's just bad design, and worth preventing.

Why not pass obj as an argument to process()?

Mark Peters
+1  A: 

What value should obj have before the for loop is run, and what value should it have after the loop is run? This would be confusing.

matt b