19

How is Java's for loop code generated by the compiler?

For example, if I have:

for(String s : getStringArray() )
{
   //do something with s
}

where getStringArray() is a function that returns the Array I want to loop on, would function be called always or only once? How optimal is the code for looping using this construct in general?

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Nikhil Garg
  • 3,944
  • 9
  • 30
  • 37
  • See [ How does the Java for each loop work? ](http://stackoverflow.com/questions/85190/how-does-the-java-for-each-loop-work). – Matthew Flaschen Aug 08 '10 at 06:18
  • See: http://stackoverflow.com/questions/1618202/in-a-java-enhanced-for-loop-is-it-safe-to-assume-the-expression-to-be-looped-ove – AHungerArtist Aug 08 '10 at 07:01
  • 1
    For the case of null collection (and not only) look https://stackoverflow.com/questions/49445634/for-each-loop-in-the-null-list?noredirect=1#comment85894805_49445634 The checked answer contains the bytecode. – Gangnus Mar 23 '18 at 09:52

4 Answers4

59

On the semantics of enhanced for loop

Here is the relevant excerpts from the Java Language Specification 3rd Edition, slightly edited for clarity:

JLS 14.14.2 The enhanced for statement

The enhanced for statement has the form:

for ( Type Identifier : Expression ) Statement

If the type of Expression is an array type, T[], then the meaning of the enhanced for statement is given by the following basic for statement:

T[] a = Expression;
for (int i = 0; i < a.length; i++) {
    Type Identifier = a[i];
    Statement
}

where a and i are compiler-generated identifiers that are distinct from any other identifiers (compiler-generated or otherwise) that are in scope at the point where the enhanced for statement occurs.

So in fact the language does guarantee that Expression will only be evaluated once.

For completeness, here's the equivalence when the Expression is of type Iterable:

JLS 14.14.2 The enhanced for statement

The enhanced for statement has the form:

for ( 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 iter = Expression.iterator(); iter.hasNext(); ) {
    Type Identifier = iter.next();
    Statement
}

where iter is a compiler-generated identifier that is distinct from any other identifiers (compiler-generated or otherwise) that are in scope at the point where the enhanced for statement occurs.

Note that it is a compile-time error if Expression is neither an Iterable nor an array, so the above two are the only cases where you can use an enhanced for loop. Also, for clarity, the above quotes leave out information regarding any labels attached on the for loop and any modifiers attached on the Identifier, but these are handled as one would expect.


On the performance of enhanced for loop

Here's a quote from Effective Java 2nd Edition, Item 46: Prefer for-each loops to traditional for loops

The for-each loop, introduced in release 1.5, gets rid of the clutter and the opportunity for error by hiding the iterator or index variable completely. The resulting idiom applies equally to collections and arrays. Note that there is no performance penalty for using the for-each loop, even for arrays. In fact, it may offer a slight performance advantage over an ordinary for loop in some circumstances, as it computes the limit of the array index only once. While you can do this by hand, programmers don't always do so.

Thus the book claims that in fact some compilers go beyond the JLS translation and performs additional optimization on the for-each loop (while still maintaining its semantics, of course).

In summary, you should not worry about the performance of for-each loop. The specification by the language is sensible (Expression only evaluated once), and precisely because this is the preferred construct in many scenarios, compilers will make sure to optimize them as best they can.

See also

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • 1
    +1 Excellent, amazing, comprehensive answer. I'd give you more than one upvote for it if I could, but sadly, I cannot. – ArtOfWarfare Dec 12 '12 at 14:44
1

JDK 1.4 introduced the RandomAccess interface. It is meant to give a hint to algorithms when, for a given List implementation, it is more efficient to iterate through:

for (int i = 0, n = list.size(); i < n; i++) {
    list.get(i);
}

than

for (Iterator i = list.iterator(); i.hasNext(); ) {
   i.next();
}

Does the foreach loop take this into account? Or does it completely ignore the fact that a given Iterable is in fact a List?

It should be noted that this would imply that adding a (iterable instanceof List && iterable instanceof RandomAccess) test and a downcast to List would work, which would add an overhead that's not always worth it and could be considered a premature optimization for a compiler syntactic sugar feature.

srborlongan
  • 4,460
  • 4
  • 26
  • 33
  • `RandomAcces` does not imply that the index based loop is more efficient. It only implies that using the index would not be significantly worse. Compare with the opposite, `LinkedList`. For this implementation, using the index loop would be disastrous. So the marker interface at other classes indicates when this is not the case. But the iterator based loop is sufficient enough for all collections, to be always used. By the way, new questions shouldn’t be posted as answers. – Holger Oct 23 '19 at 07:48
-1

Compiler might call it just once, but you can depend on it. It may not be a good coding practice. If getStringArray() returns same array each time, why not set to a variable first?

EDIT - answer changed with the comments received.

fastcodejava
  • 39,895
  • 28
  • 133
  • 186
  • 4
    You *can* in fact depend on it being called once. See http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.14.2 – Greg Hewgill Aug 08 '10 at 06:34
  • 2
    I think it's fine to invoke methods in `Expression`, within reason. `for (char c : str.toCharArray())`, `for (MyEnum e : MyEnum.values())`, etc seems idiomatic. – polygenelubricants Aug 08 '10 at 17:38
  • Why not set something that never changes to a variable? Because all that does is make a copy. – mvanlamz Nov 19 '13 at 22:14
-6

for loop is same like loop in javascript so no need to afraid

example:

for(int i=0;i<10;i++)
{
    System.out.Println(i);
}
Taryn
  • 242,637
  • 56
  • 362
  • 405
borris
  • 1