Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is foreach loop literally rewritten to a for loop with iterator? [duplicate]

This post explains that foreach loop directly corresponds to using iterator. If I write a foreach loop is it literally going to be transformed into for with iterator? In particular, given loop:

for(Integer i : createList()){
    System.out.println(i);
}

Am I guaranteed to always call createList() only once no matter what? Is it rewritten as:

for(Iterator<Integer> i = createList().iterator(); i.hasNext(); ) {
    System.out.println(i.next());
}

in some kind of intermediate step or just happens to produce the same bytecode as the above?

like image 250
Bartek Maraszek Avatar asked Apr 25 '14 11:04

Bartek Maraszek


Video Answer


2 Answers

According to Oracle documentation on this, there is indeed code being generated, but it differs according to the type of the used obejct.

If you are using an array, the foreach loop will be translated as a for loop with index:

T[] #a = Expression;
L1: L2: ... Lm:
for (int #i = 0; #i < #a.length; #i++) {
    VariableModifiersopt TargetType Identifier = #a[#i];
    Statement
    }

If you have an Iterable object, you get a loop with iterator like this:

for (I #i = Expression.iterator(); #i.hasNext(); ) {
    VariableModifiersopt TargetType Identifier = (TargetType) #i.next();
    Statement
}
like image 75
AHH Avatar answered Nov 08 '22 12:11

AHH


AFAIK, It doesn't go through a translation phase, it just does the same thing for Iterable

One difference is you cannot access the Iterator in a for-each meaning you can't do this

for(Integer i: createList()) {
   if (i == 5) iter.remove(); // or whatever the iterator is called.
}

but you can do

for(Iterator<Integer> iter = createList().iterator(); iter.hasNext(); ) {
    Integer i = iter.next();

    if (i == 5) iter.remove();
}

Note: if you have

public Integer[] createList();

then

for(Integer i : createList()){
    System.out.println(i);
}

is the same as

{
    Integer[] $arr = createList();
    for(int $i = 0; $i < $arr.length; $i++) {
        Integer i = $arr[$i];
        System.out.println(i);
    }
}

Note: The variables $arr and $i are made up and are not available to the application. You might be able to see them in your debugger, with a different name.

like image 40
Peter Lawrey Avatar answered Nov 08 '22 12:11

Peter Lawrey