for Loop
When you need to repeat a block of code a specific number of times — or iterate over a range of values — the for loop is your go-to tool. It packs the initialization, condition check, and update all into one line, making your intent crystal clear at a glance.
Basic Syntax
for (initialization; condition; update) {
// body — runs as long as condition is true
}
- initialization — runs once before the loop starts (e.g.,
int i = 0) - condition — checked before every iteration; loop stops when it becomes
false - update — runs after every iteration (e.g.,
i++)
A simple countdown example:
for (int i = 1; i <= 5; i++) {
System.out.println("Count: " + i);
}
Output:
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
The loop variable i is scoped to the loop itself — you cannot use it after the closing brace.
How Execution Flows
It helps to picture the order of operations:
- initialization executes (
int i = 1) - condition is evaluated (
i <= 5) — iffalse, skip the body entirely - body runs
- update executes (
i++) - Go back to step 2
Tip: Because the condition is checked before the body, a
forloop is a pre-condition loop — the body can run zero times if the condition starts out false.
Iterating Over an Array
The classic use case is walking through an array by index:
int[] scores = {88, 92, 75, 61, 99};
for (int i = 0; i < scores.length; i++) {
System.out.println("Score[" + i + "] = " + scores[i]);
}
Output:
Score[0] = 88
Score[1] = 92
Score[2] = 75
Score[3] = 61
Score[4] = 99
Note: Always use
i < scores.length(strictly less than), noti <= scores.length. Using<=causes anArrayIndexOutOfBoundsExceptionon the last iteration.
When you only need the values — not the index — prefer the for-each loop instead; it is shorter and less error-prone.
Counting Down
You can initialize i to the highest value and decrement:
for (int i = 5; i >= 1; i--) {
System.out.println(i);
}
System.out.println("Liftoff!");
Output:
5
4
3
2
1
Liftoff!
Stepping by More Than One
The update expression can be any valid statement — not just i++:
// Print even numbers from 2 to 10
for (int i = 2; i <= 10; i += 2) {
System.out.print(i + " ");
}
Output:
2 4 6 8 10
Nested for Loops
You can place a for loop inside another. Each iteration of the outer loop triggers a complete run of the inner loop — classic for building grids or multiplication tables:
for (int row = 1; row <= 3; row++) {
for (int col = 1; col <= 3; col++) {
System.out.printf("%4d", row * col);
}
System.out.println();
}
Output:
1 2 3
2 4 6
3 6 9
Warning: Deeply nested loops (3+ levels) multiply quickly. A triple loop over
nelements is O(n³) — watch out for performance issues with large data sets.
Declaring Multiple Variables
You can declare and initialize multiple variables of the same type in the initialization section, separated by commas:
for (int i = 0, j = 10; i < j; i++, j--) {
System.out.println("i=" + i + ", j=" + j);
}
Output:
i=0, j=10
i=1, j=9
i=2, j=8
i=3, j=7
i=4, j=6
Note: Both variables must share the same type (
inthere). You cannot mixint i = 0, long j = 10in a single init clause.
Omitting Parts of the Header
All three sections of the for header are optional. You can omit any or all of them (but keep the semicolons):
int i = 0;
for (; i < 3; ) { // init and update moved outside
System.out.println(i);
i++;
}
Omitting all three creates an infinite loop — useful when you control exit with break:
for (;;) {
// runs forever unless a break or return is hit
}
Tip: An infinite loop with
breakis occasionally useful (e.g., event loops), but make sure there is always a reachable exit path, or your program will hang.
Using break and continue
breakexits the loop immediately.continueskips the rest of the current iteration and jumps straight to the update step.
for (int i = 0; i < 10; i++) {
if (i == 7) break; // stop at 7
if (i % 2 == 0) continue; // skip even numbers
System.out.print(i + " ");
}
Output:
1 3 5
Labeled Loops
When you have nested loops and want break or continue to target the outer loop, use a label:
outer:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (j == 1) continue outer; // skip rest of inner, go to next outer iteration
System.out.println("i=" + i + ", j=" + j);
}
}
Output:
i=0, j=0
i=1, j=0
i=2, j=0
Labels are rarely needed, but they are cleaner than setting a boolean flag when you need to jump out of multiple nesting levels.
Under the Hood
Bytecode Translation
The Java compiler translates a for loop into a simple conditional branch in bytecode. This pseudocode of the bytecode roughly looks like:
INIT
LABEL_start:
evaluate CONDITION → boolean
if false → GOTO LABEL_end
BODY
UPDATE
GOTO LABEL_start
LABEL_end:
There is no special “for loop” bytecode instruction — it compiles down to the same goto-based pattern as a while loop. The difference is purely syntactic sugar at the Java source level.
JIT Optimizations
The JVM’s Just-in-Time compiler (JIT) applies several aggressive optimizations once a loop is detected as “hot” (executed many times):
- Loop unrolling — repeats the body 2–8 times per iteration to reduce branch overhead.
- Auto-vectorization — rewrites array-walking loops into SIMD CPU instructions that process multiple elements in parallel.
- Range-check elimination — for loops like
for (int i = 0; i < arr.length; i++), the JIT proves array accessarr[i]is always in bounds and removes the per-access check. - Induction variable optimization — hoists loop-invariant computations (e.g.,
arr.length) out of the loop so they are not re-evaluated on every iteration.
This is why a hand-written for loop in Java can approach native C performance for number-crunching tasks — the JIT does a lot of the heavy lifting automatically.
Stack Frame Behavior
Each loop iteration does not create a new stack frame. The loop variable lives in the existing method’s local variable table (a slot in the stack frame), and the update simply overwrites that slot on each pass. This makes tight loops very memory-efficient.
Common Mistakes
| Mistake | Problem | Fix |
|---|---|---|
i <= arr.length | ArrayIndexOutOfBoundsException on last access | Use i < arr.length |
i = i + 1 inside body and i++ in update | Counter increments twice per iteration | Pick one place to update |
| Modifying the collection while iterating | ConcurrentModificationException or skipped elements | Use an iterator or copy the collection |
Floating-point loop counter (for (double x = 0.0; x != 1.0; x += 0.1)) | Accumulating rounding error means x may never equal 1.0 exactly | Use an integer counter and compute the float value inside the body |
Related Topics
- for-each Loop — cleaner syntax when you only need the values, not the index
- while Loop — better when the number of iterations is not known upfront
- do-while Loop — guarantees at least one execution of the body
- break Statement — exit a loop early based on a condition
- continue Statement — skip an iteration without exiting the loop
- How Loops Work (Bytecode & JIT) — a deeper dive into how the JVM compiles and optimizes loop constructs