Mittwoch, 8. Juli 2015

For Loop Scoping is Evil

Try the following in Java 7:

import java.util.List;
import java.util.ArrayList;

public class Test {
    private final List<Object> a = new ArrayList<>();

    public void doSomething()
    {
        for (Object a: a) {
        }
    }
}

As you probably expected, this does not compile, because you cannot iterate over an Object (and Object a should shadow the private field):

  error: for-each not applicable to expression type
        for (Object a: a) {
                       ^
  required: array or java.lang.Iterable
  found:    Object
However, if you consult the JLS, this behaviour is actually wrong:

The enhanced for statement is equivalent to a basic for statement of the form:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
    VariableModifiersopt TargetType Identifier =
        (TargetType) #i.next();
    Statement
}
That is, according to the specification, Object a is meant to be declared inside the for loop's block after the outer a (Expression) has already been evaluated.

Java 8 corrects this mismatch between specification and implementation and the code above compiles fine.

The effects however, are probably counter-intuitive. The enhanced for loop switches around the declaration of the variable as it appears in the code (Object a) and the point in the program where the declaration takes effect.

Keine Kommentare:

Kommentar veröffentlichen