for Loop
The for loop packs initialization, a condition, and an update into a single header, making it the natural choice whenever you know roughly how many times you want to repeat something.
A for loop is Java's most compact repetition construct: it bundles setup, a continuation test, and a per-iteration update into one header, then repeats a body while the test holds. It is the workhorse of counted iteration — walking arrays, generating sequences, and driving nested computations.
What Is a for Loop, and Why Use One
A for loop repeats a block of statements while a boolean condition remains true, with the loop's bookkeeping (starting value, stopping test, and step) written together in one place. This is different from a while loop, where you write the initialization before the loop and the update somewhere inside the body — spread out and easy to forget.
Use a for loop whenever the number of iterations is known or countable ahead of time: iterating indices 0 through n-1, counting down, or stepping through a range. When the stopping condition instead depends on something discovered during the loop (like reading input until a sentinel value appears), a while loop usually reads more naturally.
Anatomy: Initialization, Condition, Update
The for header has three semicolon-separated parts: for (initialization; condition; update) { body }.
initialization runs once, before the loop starts. condition is checked before every iteration, including the first. update runs after each iteration's body, right before the condition is checked again.
for (int i = 0; i < 5; i++) {
System.out.println("i = " + i);
}Execution order for the loop above:
init: i = 0
check: 0 < 5 -> true -> body (prints "i = 0")
update: i++ (i = 1)
check: 1 < 5 -> true -> body (prints "i = 1")
... continues ...
update: i++ (i = 5)
check: 5 < 5 -> false -> loop exitsBasic Syntax and Execution Order
Formally: for (ForInit; Expression; ForUpdate) Statement. ForInit typically declares and initializes one or more variables; Expression must evaluate to boolean; ForUpdate is one or more expression statements (increment, decrement, assignment, or method calls), separated by commas.
// Braces are optional for a single-statement body, but strongly recommended
for (int i = 0; i < 3; i++)
System.out.println(i); // works, but easy to misread later
for (int i = 0; i < 3; i++) {
System.out.println(i); // preferred: unambiguous, easy to extend
}Scope of the Loop Variable
A variable declared in the initialization clause (like int i above) is scoped to the loop itself — it does not exist before the loop and is not accessible after it ends. This is usually exactly what you want: a throwaway counter that cannot leak into surrounding code.
If you need the final counter value after the loop, declare the variable before the loop and omit it from the initialization clause.
for (int i = 0; i < 3; i++) {
// i is visible here
}
// i is NOT visible here - compile error if referenced
// System.out.println(i); // error: cannot find symbolint i;
for (i = 0; i < 3; i++) {
// ...
}
System.out.println("Loop ended with i = " + i); // i = 3Nested for Loops
A for loop can contain another for loop. Each iteration of the outer loop runs the entire inner loop to completion. This is the standard way to walk two dimensions — rows and columns of a grid, or all pairs from two collections.
Use different variable names for each nesting level (i, j, k or row, col) — reusing the same name in an inner loop's own header simply shadows the outer one within that scope, which compiles but is a common source of confusion.
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
System.out.print(row + "," + col + " ");
}
System.out.println();
}
// 0,0 0,1 0,2
// 1,0 1,1 1,2
// 2,0 2,1 2,2Infinite for Loops
A for loop runs forever if its condition is always true or omitted entirely. for (;;) { } is idiomatic Java for an intentional infinite loop, usually paired with an internal break to exit.
An unintentional infinite loop is more often a bug: forgetting the update, updating the wrong variable, or writing a condition that can never become false for the values the update produces.
int attempts = 0;
for (;;) {
attempts++;
if (tryConnect()) {
break; // only way out
}
if (attempts >= 5) {
throw new IllegalStateException("Could not connect after 5 attempts");
}
}Omitting Parts of the Header
Any of the three header parts may be empty, as long as the semicolons stay. This is legal but should be used sparingly and with a comment, since it departs from the reader's expectation of seeing all three parts.
int i = 0;
for (; i < 5; i++) { // initialization done earlier
System.out.println(i);
}
for (int j = 0; j < 5;) { // update happens inside the body
System.out.println(j);
j += 2;
}Multiple Variables in the Header
The initialization and update clauses can each hold several comma-separated statements, as long as every declared variable in the initialization shares the same type.
for (int i = 0, j = 10; i < j; i++, j--) {
System.out.println("i=" + i + " j=" + j);
}for vs Enhanced for (for-each)
The classic for shown here gives you an explicit index and full control over the start, step, and direction of iteration. Java also has an enhanced for (for-each) form, for (Type element : collectionOrArray), which reads each element in turn without exposing an index at all.
Prefer the enhanced for when you only need each element's value and don't need the index, don't need to modify the underlying array/collection in place by index, and don't need to iterate backwards or skip elements. Reach for the classic for when any of those apply.
int[] values = {10, 20, 30};
// classic for: index available, can skip, go backwards, or step by more than 1
for (int i = 0; i < values.length; i++) {
System.out.println(i + " -> " + values[i]);
}
// enhanced for: simplest form when you only need the values
for (int v : values) {
System.out.println(v);
}Practical Usage Patterns
Common counted-iteration tasks: summing values, building a string, searching by index, counting down, and stepping through an array by a fixed stride.
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println("Sum 1..100 = " + sum); // 5050
// countdown
for (int i = 5; i >= 1; i--) {
System.out.println(i);
}
// every other element
int[] data = {1, 2, 3, 4, 5, 6, 7, 8};
for (int i = 0; i < data.length; i += 2) {
System.out.println(data[i]);
}Edge Cases
If the condition is false the very first time it is checked, the body never executes at all — not even once. This differs from do-while, which always runs its body at least once.
Looping over an empty array or an array with a single element both work correctly with the same header pattern — array.length naturally evaluates to 0 or 1, so no special-casing is needed.
for (int i = 10; i < 5; i++) {
System.out.println("never printed");
}
System.out.println("loop skipped entirely");Complete Example
Nested for loops build a small multiplication table: the outer loop picks the row, the inner loop builds that row one column at a time.
public class Multiplication {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
StringBuilder row = new StringBuilder();
for (int j = 1; j <= n; j++) {
row.append(String.format("%4d", i * j));
}
System.out.println(row);
}
}
}Mental Model
Think of a for loop as: run init once, then repeat { check condition -> if false, stop; else run body; then run update } forever until the condition fails. All three header clauses only ever interact with the condition check and the body — they are just a compact way of writing what you'd otherwise spread across separate statements around a while loop.
Quick Reference
for (init; condition; update) { body }
init runs once, before anything else
condition checked before every iteration (including the first)
body runs only while condition is true
update runs after body, before the next condition check
for (;;) { } infinite loop (typically with an internal break)
for (int i=0,j=9; ...) {} multiple init/update variables
for (Type x : collection) enhanced for (for-each)Key Takeaways
A for loop bundles initialization, condition, and update into one header, executed in that fixed order: init, then check-body-update repeatedly.
The condition is checked before every iteration, so the body may run zero times if it starts out false.
A variable declared in the header is scoped to the loop and disappears after it — declare it beforehand if you need its final value.
Any header clause can be omitted, and for (;;) is idiomatic for an intentional infinite loop.
Prefer the classic for when you need an index, need to skip/reverse/step, or need to know how many iterations ran; prefer the enhanced for otherwise.
for (int i = 0; i <= array.length; i++) { System.out.println(array[i]); } for (int i = 0; i < array.length; i++) { System.out.println(array[i]); }
Using <= against .length causes an ArrayIndexOutOfBoundsException on the last iteration, since valid indices only go up to length - 1.
for (int i = 0; i < 10; i++); { System.out.println(i); // also a compile error: i is out of scope here } for (int i = 0; i < 10; i++) { System.out.println(i); }
A stray semicolon right after the header creates an empty loop body that runs ten times doing nothing; the following block then runs once, unrelated to the loop.
for (int i = 10; i < 20; i--) { System.out.println(i); } for (int i = 10; i < 20; i++) { System.out.println(i); }
The condition (i < 20) and the update (i--) move in opposite directions, so the condition is either immediately false or, worse, never becomes false — an infinite loop.
for (int i = 0; i < list.size(); i++) { if (shouldRemove(list.get(i))) { list.remove(i); // shifts later elements down, skipping one } } for (int i = list.size() - 1; i >= 0; i--) { if (shouldRemove(list.get(i))) { list.remove(i); } }
Removing by index while iterating forward shifts subsequent elements down, causing the next index to skip an element; iterating backwards avoids the shift problem.
What does for (int i = 0; i < 5; i++) guarantee about how many times the body runs if nothing inside it changes i?
Exactly 5 times, for i = 0, 1, 2, 3, and 4 — the loop stops as soon as the condition (i < 5) evaluates to false, which happens right after i becomes 5.
Why does int i declared in a for loop's initialization clause become inaccessible after the loop ends?
Because Java scopes that declaration to the for statement itself; it is created when the loop starts and goes out of scope when the loop (including its header) finishes, exactly like a variable declared inside any other block.
Is for (;;) { } valid Java, and what does it do?
Yes — all three header clauses are optional as long as the semicolons remain. With no condition, it is treated as always true, so the loop runs forever unless something inside the body (like break, return, or an exception) stops it.
Given for (int i = 0; i < arr.length; i++), why is < used instead of <=?
Array indices run from 0 to length - 1. Using <= would let i reach arr.length on the final check, and arr[arr.length] is out of bounds, throwing ArrayIndexOutOfBoundsException.
What is the practical difference between a classic for loop and an enhanced for loop when processing an int[]?
The classic for exposes an index you can use to skip elements, go backwards, or write into the array; the enhanced for only reads each value in forward order and never exposes an index, which is simpler but less flexible.
Why should nested loops generally use different variable names for each level (e.g. i and j) rather than reusing i everywhere?
Reusing the same name in a nested loop's own header creates a new, separate variable that shadows the outer one only within the inner loop's scope; it compiles, but is confusing to read and easy to misuse if you ever need to refer to the outer counter from inside the inner loop.
What happens if the condition in a for loop is false the first time it's evaluated?
The body never executes — not even once — and control passes immediately to whatever follows the loop.
Write a for loop that prints all even numbers from 2 to 20 inclusive.
for (int i = 2; i <= 20; i += 2) { System.out.println(i); } Starting at 2 and incrementing by 2 each time naturally lands on every even number; the condition i <= 20 includes 20 itself since the target range is inclusive.
What does this print?
30 — it sums i*i for i = 1, 2, 3, 4 (since i < 5 excludes 5), giving 1 + 4 + 9 + 16 = 30.
Write a nested for loop that prints a right triangle of asterisks with 4 rows (1 star in row 1, up to 4 stars in row 4).
for (int row = 1; row <= 4; row++) { for (int col = 1; col <= row; col++) { System.out.print("*"); } System.out.println(); }
The outer loop picks the row number (1 through 4); the inner loop's condition col <= row makes it print exactly as many stars as the current row number, then a newline ends the row.
What does this print (trace it through)?
01 02 10 12 20 21 — for each i, the inner loop skips printing when j equals i (continue jumps to the next j), so the pair where i and j match is omitted, and everything else is printed in order.
int total = 0;
for (int i = 1; i < 5; i++) {
total += i * i;
}
System.out.println(total);for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (j == i) continue;
System.out.print(i + "" + j + " ");
}
}