Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's happening under the hood of an enhanced for loop?

Tags:

java

foreach

I wrote the following test when exploring Java's enhanced for loop:

class test
{
    int number = 0;

    public static void main(String args[]) {
        new test();
    }

    public test() {

        int[] numbers = getNumbers();

        for(int number : numbers) {
            System.out.println("number    : " + number);
            System.out.println("numbers[0]: " + numbers[0]);

            numbers = getNumbers();
        }
    }

    public int[] getNumbers() {

        number++;

        int[] numbers = new int[5];

        for(int i = 0; i < numbers.length; i++)
            numbers[i] = number;

        return numbers;
    }
}

I was surprised to find my test ouputted:

number    : 1
numbers[0]: 1
number    : 1
numbers[0]: 2
number    : 1
numbers[0]: 3
number    : 1
numbers[0]: 4
number    : 1
numbers[0]: 5

It appears then that a separate instance of numbers is created when the loop is first executed, and is made immutable. From there, any changes made to numbers are only made to the version which exists outside the loop condition.

I've confirmed the behavior is at least similar to this by replacing the loop with:

for(int number : numbers) {
    System.out.println("number    : " + number);
    numbers = null;
}

which gave:

number    : 1
number    : 1
number    : 1
number    : 1
number    : 1

My question is: what behavior is being hidden from us here? Is a second version of numbers copied? Is it actually immutable, or have I not poked it hard enough? In other words:

What's happening under the hood of an enhanced for loop?

like image 978
Lord Farquaad Avatar asked Jun 11 '18 20:06

Lord Farquaad


People also ask

How does an enhanced for loop work?

How it works? The Java for-each loop traverses the array or collection until the last element. For each element, it stores the element in the variable and executes the body of the for-each loop.

What are some of the reasons you would use an enhanced for each loop instead of a for loop?

6-3-4: What are some of the reasons you would use an enhanced for-each loop instead of a for loop? I: If you wish to access every element of an array. II: If you wish to modify elements of the array. III: If you wish to refer to elements through a variable name instead of an array index.

Is enhanced for loop faster than for loop?

It's a bit of an oversimplification to say that the enhanced for loop is more efficient. It can be, but in many cases it's almost exactly the same as an old-school loop.


1 Answers

The enhanced for loop is covered by the JLS, Section 14.14.2:

  • For Iterable objects:

The enhanced for statement is equivalent to a basic for statement of the form:

for (I #i = Expression.iterator(); #i.hasNext(); ) {
    {VariableModifier} TargetType Identifier =
        (TargetType) #i.next();
    Statement
}
  • For arrays:

The enhanced for statement is equivalent to a basic for statement of the form:

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

It creates a new reference to the array, separate from your original reference. You can modify the reference to the array all you want, but it will still keep iterating over this implicit reference to the original array.

Over Iterables, only the reference to the Iterator is kept, which still refers back to the original Iterable object, even if you reassign the original variable during the loop.

Whether you use an enhanced for loop over an array or an Iterable, you can reassign the reference used as the target without affecting the result of the iteration -- you will still iterate over the original object referred by the target reference.

like image 195
rgettman Avatar answered Oct 02 '22 21:10

rgettman