Section4.6For-Each Loops: Syntactic Sugar for Iteration
In the previous section, we built a custom iteration class (MyIterator) that encapsulated an array and a current index—essentially acting as a "bookmark" into the data. That approach frees us from manually writing for loops (with index checks) everywhere.
However, imagine if you could simply hand off your array to a built-in mechanism that knows how to iterate without exposing the raw index. In Java, the enhanced for loop (often called the for-each loop) provides exactly this convenience. It’s a form of syntactic sugar—a concise way to perform iteration without writing out all the loop-control details.
Our goal in this section is to show you how to use the for-each loop with arrays, compare its behavior to the iteration logic you already built, and discuss subtle pitfalls to watch out for. Later, as you learn about interfaces and inheritance, you’ll see how to adapt your custom classes so that they plug directly into the for-each syntax.
int[] numbers = {5, 10, 15, 20};
for (int num : numbers) {
System.out.println("Number: " + num);
}
The syntax for (int num : numbers) is short for “Loop over each element of numbers, assign it to num, then run the body.” It’s the same fundamental iteration—just no explicit index variable or length checks. Think of it like Java calling hasNext() and next() behind the scenes for each element.
Each iteration, num becomes one element of numbers. Once it exhausts the array, the loop ends automatically—no extra condition or index update required.
No Easy Way to Remove/Insert: Because arrays are fixed-size and for-each doesn’t provide the index, you can’t remove or insert elements mid-loop (like you might in a dynamic list). You can modify the element values themselves, but you can’t skip or reorder them easily using for-each.
Breaking Early or Skipping Elements: If you need to exit after you find a certain element, you can do so with a break inside the for-each body—but skipping certain indices or iterating in reverse is better handled by a classic for loop or a while.
Overall, for-each loops excel at “visit every element in a forward direction with minimal fuss.” If you want more control—like indexing, reordering, or partial iteration—then a classic for or while might be better.
Subsection4.6.3Relating For-Each to Our MyIterator Class
Recall that our MyIterator class had methods hasNext() and next() to manage iteration. Java’s for-each loop relies on the same idea but in a more standardized way using interfaces and generics:
Note4.6.1.
An interface in Java defines a contract that a class must follow if it implements that interface. The Iterator<T> and Iterable<T> interfaces formalize how iteration should work, ensuring consistency across different types.
Generics (<T>) allow these interfaces to work with any data type rather than being restricted to a specific one. This makes iterators more reusable and type-safe.
But don’t worry too much about interfaces and generics for now, we’ll cover them in more detail later. This is just a stepping stone to help us see how Java handles iteration under the hood. The key idea is that Java’s for-each loop works by relying on hasNext() and next(), just like our MyIterator class.
Our MyIterator is close to that pattern. Later, once we learn about interfaces and generics, we can rework MyIterator to formally implement Iterator<Integer>. We could also create a separate class that implements Iterable<Integer> (returning a new MyIterator in its iterator() method). Then for-each would just “magically” work.
// Pseudo-code of what for (T item : collection) is doing:
Iterator<T> it = collection.iterator();
while (it.hasNext()) {
T item = it.next();
// loop body
}
Because our MyIterator was built from first principles, you have a deeper appreciation for what happens under the hood!
int[] data = {2, 11, 4, 6, 9, 2};
int totalEven = 0;
for (int val : data) {
if (val % 2 == 0) {
totalEven += val;
}
// If we only want to sum the first 3 array elements total:
// This won't help if we need to stop after the 3rd element.
// for-each doesn't give an index.
}
System.out.println("Sum of even numbers: " + totalEven);
That sums all even numbers (2 + 4 + 6 + 2 = 14). However, if we needed to stop after the 3rd element in the array or skip certain positions, we’d realize for-each can’t easily do that. We’d have to add an external counter or break logic:
int count = 0;
int sumEvens = 0;
for (int val : data) {
sumEvens += (val % 2 == 0) ? val : 0;
count++;
if (count == 3) {
break; // we processed 3 elements, let's stop
}
}
System.out.println("Sum of even numbers in the FIRST 3 elements: " + sumEvens);
That works but starts feeling awkward. If you need to break frequently or refer to indexes, a classic for loop is often simpler.
Key takeaway: For-each loops are clean and short for “iterate all elements,” but less flexible when partial iteration or index-based operations are required.
Let’s put your new skills to the test! The following exercises reinforce how for-each loops can simplify your code for straightforward iteration tasks.
Exercise 2: Given the following array of names, use a for-each loop to print a personalized greeting for each name. For example, if the array contains {"Alice", "Bob", "Charlie"}, the output should be:
Exercise 3: Can We Modify Each Element? Suppose we have int[] scores = {2, 4, 6}; and want to double each value. Try using a for-each loop, then print the array. Observe whether the final array actually changed or not. Then fix the code (hint: we must use a standard for loop or some trick).
For-each loops are best for “visit every element, forward only,” with minimal fuss. If you need random access, skipping, or partial iteration, you might revert to a traditional loop.
With this knowledge, you can write cleaner, more expressive loops in your Java programs when you just need to process each element. In the next chapter, we’ll delve deeper into classes and objects (including interfaces and inheritance) and see how the standard Iterator and Iterable interfaces power Java’s for-each loop across various collections—beyond just arrays.