I have this for-each-loop:
for (Component c : container.getComponents()) {
// Loop code
}
Is getComponents
called on every iteration? Does it make sense to call getComponents
before the look and only work on a cached array?
I have this for-each-loop:
for (Component c : container.getComponents()) {
// Loop code
}
Is getComponents
called on every iteration? Does it make sense to call getComponents
before the look and only work on a cached array?
I would have thought that when compiled, it would be translated to be a "long hand" for loop, as in using for(int i = 0 ....
Isn't the foreach loop just a programming time saver with the actual bytecode translation the same as doing it "long hand"??
In short, getComponent() should only be called once
getComponents will be called once, and will return an Iterator. This iterator will then be called using next() and hasNext() methods.
Update Here's a bit more detail in attempt to out Skeet Jon Skeet on this answer.
The following program shows how the call to iterator
is made once, even though there are three items in the collection.
public static void main(String[] args) {
List<String> list = new ArrayList<String>() {
public java.util.Iterator<String> iterator() {
System.out.println("iterator() called");
return super.iterator();
};
};
list.add("a");
list.add("b");
list.add("c");
for (String s : list) {
System.out.println(s);
}
}
Output:
iterator() called
a
b
c
If you run this through a Java decompiler, you'll find the following code:
String s;
for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(s))
s = (String)iterator.next();
Addtionally, since we know from the JLS 14.14.1 that the first section of a for statement is only executed once, we can rest assured that iterator method won't be called multiple times.
No, getComponents() will only be called once.
It's the equivalent of:
for (Iterator<Component> iterator = container.getComponents().getIterator();
iterator.hasNext(); )
{
Component c = iterator.next();
...
}
From section 14.14.2 of the Java Language Specification:
The enhanced for statement has the form:
EnhancedForStatement:
for ( VariableModifiersopt Type Identifier: Expression) Statement
The Expression must either have type Iterable or else it must be of an array type (§10.1), > or a compile-time error occurs. The scope of a local variable declared in the FormalParameter part of an enhanced for statement (§14.14) is the contained Statement
The meaning of the enhanced for statement is given by translation into a basic
for
statement.If the type of Expression is a subtype of
Iterable
, then let I be the type of the expressionExpression.iterator()
. The enhanced for statement is equivalent to a basicfor
statement of the form:for (I #i = Expression.iterator(); #i.hasNext(); ) { VariableModifiersopt Type Identifier = #i.next(); Statement }
Is getComponents called on every iteration?
No. Java's foreach loop is based on the Iterable interface, and is equivalent to this code
Iterator<Component> i = container.getComponents().iterator
while(i.hasNext()) {
Component c = i.next();
// loop body goes here
}
The only difference is that the Iterator is hidden.
Java LanguageSpecification 14.14.2 says:
EnhancedForStatement:
for ( VariableModifiersopt Type Identifier: Expression) Statement
If the type of Expression is a subtype of Iterable, then let I be the type of the expression Expression.iterator(). The enhanced for statement is equivalent to a basic for statement of the form:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
VariableModifiersopt Type Identifier = #i.next();
Statement
}
Where #i is a compiler-generated identifier that is distinct from any other identifiers (compiler-generated or otherwise) that are in scope (§6.3) at the point where the enhanced for statement occurs.
So the expression is evaluated only once (during initialization).