Concepts / Arrays and Memory Layout in Java

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.

  • Programming

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?

  • The array now holds 17, 17 and 17

  • The array still holds 4, 8 and 15

  • The array holds only the last value assigned, 17

Reveal answer
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.

Definition

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.

numbers[0]4numbers[1]8item8numbers[2]15value read on pass two
What is the difference between an array slot holding a value and the loop variable holding a copy of that value?

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.

Code walkthrough
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));
    }
}
  1. 1
    Line 4 creates an array with three values.
  2. 2
    Line 5 starts the for-each loop, which supplies one value per pass to item.
  3. 3
    Line 6 computes a new value and assigns it to item, not to numbers.
  4. 4
    Line 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
Output
[4, 8, 15]
Before
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.

After
int[] numbers = {4, 8, 15};
for (int item : numbers) {
    item = 17;
}
// numbers still holds 4, 8, 15

The loop has finished. item was reassigned on each pass, but the array still holds 4, 8 and 15.

numbers[0]4numbers[0]4item4item17
When the body runs item = 17 on the first pass, which value changes, and what stays the same in the array?

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.

Code walkthrough
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));
    }
}
  1. 1
    Line 5 starts an indexed loop that counts from 0 to the last index.
  2. 2
    Line 6 reads numbers[i], multiplies it by 2, and stores the result back into numbers[i].
  3. 3
    Line 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
Output
[8, 16, 30]
numbers[0]8numbers[1]16numbers[2]30
Which slots change when the loop runs numbers[i] = numbers[i] * 2, and what value does each slot hold afterward?

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 like
    for (int item : numbers) { item = 17; }
    Why it fails

    item 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 instead

    Use 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 fails

    A 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 instead

    Use an indexed loop that starts and ends at the positions you need.

  • Common mistake

    Expecting a for-each loop to run backward

    Why it fails

    The for-each loop moves forward through the array only.

    Do this instead

    Use an indexed loop that counts down from numbers.length - 1 to 0.

Choosing Between the Two Loop Styles

QuestionFor-each loopIndexed loop
What does the loop give access to?The values, one per passThe position and the slot at that position
Can it change array elements?No, assignment changes only the loop variableYes, by assigning to numbers[i]
Can it start mid-array or run in reverse?NoYes, by choosing the start, end and step of the index
Best fitReading every value in orderModifying elements or processing part of the array

Comparing what each loop style gives access to and which tasks suit it

Practice Tracing Loops

MEDIUM

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].