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?
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.
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.
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.
The enhanced for
loop is covered by the JLS, Section 14.14.2:
Iterable
objects:The enhanced
for
statement is equivalent to a basicfor
statement of the form:for (I #i = Expression.iterator(); #i.hasNext(); ) { {VariableModifier} TargetType Identifier = (TargetType) #i.next(); Statement }
The enhanced
for
statement is equivalent to a basicfor
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 Iterable
s, 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With