Arrays and Memory Layout in Java
A for-each loop processes the values in an array, not the elements themselves, so assigning to the loop variable does not change the array.
A Loop That Seems to Fill the Array
A for-each loop looks like it hands you each position of an array, one after another. Because of that, many learners assume that writing to the loop variable will write into the array. It is natural to expect that a line such as item = 17 inside the loop will fill the array with 17s. This article tests that belief against what the loop actually does, and it shows where the for-each loop is a good fit and where it is not.
What do you think happens?
Suppose an array holds 4, 8 and 15, and a for-each loop runs the body item = 17 on every pass. What do the array's values look like after the loop finishes?
Reveal answer
The array still holds 4, 8 and 15.
The for-each loop supplies values to the loop variable, not the array slots themselves. Assigning to item only changes the name item, so the array keeps the values it had before the loop started.
Values Versus the Elements That Hold Them
The key to this topic is a distinction between two words that sound alike in everyday speech. A value is the piece of data stored in a slot. An element is the actual memory location that is part of the array and that holds the value. The array is the collection of these elements, and each element carries one value at a time.
A value is the data stored in a slot. An array element is the memory location that is part of the array and holds one value. The loop variable is a separate name that is given a value for one pass through the loop body.
The diagram below shows these pieces side by side. The array has its own slots, and the loop variable is a separate name. On the first pass, the loop reads the value from one slot and gives that value to item. The arrow marks that read. Nothing in the diagram connects item back to the slot, so no later statement inside the body can reach the slot through item.
Tracing the Loop Variable Step by Step
Read the loop variable as a name that is given a value for one pass through the body. When the body executes item = 17, the name item is now associated with 17. The array element that supplied the value was never named in that statement, so nothing in the array is reached. The next pass gives item the next value from the array, and the earlier assignment is simply replaced.
import java.util.Arrays;
public class ForEachReassign {
public static void main(String[] args) {
int[] numbers = {4, 8, 15};
for (int item : numbers) {
item = item * 2;
}
System.out.println(Arrays.toString(numbers));
}
}- 1Line 4 creates an array with three values.
- 2Line 5 starts the for-each loop, which supplies one value per pass to item.
- 3Line 6 computes a new value and assigns it to item, not to numbers.
- 4Line 8 prints the array, which still contains the original values.
- The loop variable item receives each value from numbers in turn
- item = item * 2 changes only the name item for that pass
- The array itself is never the target of the assignment
[4, 8, 15]int[] numbers = {4, 8, 15};
for (int item : numbers) {
item = 17;
}The array holds 4, 8 and 15 and the loop is about to start.
int[] numbers = {4, 8, 15};
for (int item : numbers) {
item = 17;
}
// numbers still holds 4, 8, 15The loop has finished. item was reassigned on each pass, but the array still holds 4, 8 and 15.
The three array cells in the picture stand in for the full array, and the same reasoning applies to every slot. Only the loop variable is reassigned. The array cells keep the values they had before the loop started, which is why the printed result in the code example is still 4, 8, 15.
Why the Assignment Never Reaches the Array
The for-each loop is built around values. On each pass it supplies the next value from the array to the loop variable. The loop does not hand you the element itself, so changing the loop variable has no effect on the array. The earlier assignment is simply replaced when the next value arrives on the following pass.
When a For-Each Loop Is Not the Right Tool
The for-each loop is a good fit when you want to read every value in order. It makes the code a little simpler because it removes the need for array indices. Its strength is that case, so it is not the right choice in every situation. Two common situations do not suit it: processing only part of an array, and walking the elements in reverse order.
Writing New Values Through an Index
When the goal is to change the array, the loop has to name the slot being changed. An indexed loop does this by using the index to refer to the element directly. The index i identifies one slot on each pass, so an assignment to numbers[i] writes a new value back into that position. The example below is an illustration written for this article. It performs the same doubling task that failed in the for-each version, and this time the array changes.
import java.util.Arrays;
public class IndexedWrite {
public static void main(String[] args) {
int[] numbers = {4, 8, 15};
for (int i = 0; i < numbers.length; i++) {
numbers[i] = numbers[i] * 2;
}
System.out.println(Arrays.toString(numbers));
}
}- 1Line 5 starts an indexed loop that counts from 0 to the last index.
- 2Line 6 reads numbers[i], multiplies it by 2, and stores the result back into numbers[i].
- 3Line 8 prints the array, which now holds the doubled values.
- The index i selects one slot on each pass
- numbers[i] on the left side names the slot being written
- The right side reads the same slot before the new value is stored
[8, 16, 30]Each slot is visited through its index, and each write lands in that same slot. This is the reason the indexed loop can modify the array, while the for-each loop could only read it.
Mistakes With For-Each Loops
Common mistake Expecting the array to change when the loop variable is assigned
What it looks likefor (int item : numbers) { item = 17; }Why it failsitem is a name given a value for one pass. The assignment replaces that value for the name, not the slot the value came from.
Do this insteadUse an indexed loop and assign to numbers[i] when the array must change.
Common mistake Using a for-each loop when only part of the array should be processed
Why it failsA for-each loop always starts at the first value and runs to the last, so it cannot skip to a chosen starting position.
Do this insteadUse an indexed loop that starts and ends at the positions you need.
Common mistake Expecting a for-each loop to run backward
Why it failsThe for-each loop moves forward through the array only.
Do this insteadUse an indexed loop that counts down from numbers.length - 1 to 0.
Choosing Between the Two Loop Styles
| Question | For-each loop | Indexed loop |
|---|---|---|
| What does the loop give access to? | The values, one per pass | The position and the slot at that position |
| Can it change array elements? | No, assignment changes only the loop variable | Yes, by assigning to numbers[i] |
| Can it start mid-array or run in reverse? | No | Yes, by choosing the start, end and step of the index |
| Best fit | Reading every value in order | Modifying elements or processing part of the array |
Comparing what each loop style gives access to and which tasks suit it
Practice Tracing Loops
An array holds the values 3, 6 and 9. A learner writes for (int x : values) { x = x + 10; } and then prints the array. Predict the printed result, then explain which part of the array, if any, was changed and why. Then rewrite the loop so that every value in the array increases by 10.
Hints
- Ask which name is being assigned: the loop variable or an array slot.
- The rewritten loop needs to name the slot, so think about which index refers to it.
- Print the array after the loop to check your prediction.
Key Takeaways
- A for-each loop supplies values from an array to its loop variable, so assigning to the loop variable does not change the array.
- An array value is the data in a slot, while an array element is the memory location that holds that value; the loop variable is a separate name.
- A for-each loop suits reading every value in order, but it cannot process only part of an array or walk it in reverse.
- To modify array elements, use an indexed loop and assign to the specific slot, such as numbers[i].