for loop in Java
Init; condition; update, and off-by-one errors.
Three parts, one line
A for header holds init (runs once), condition (checked before each pass) and update (runs after each pass). Order: init, check, body, update, check, body, update... The first pass sees i == 0; the update hasn't run yet.
for (int i = 0; i < 3; i++) {
System.out.println(i);
} // 0, 1, 2Your turn
What prints?
for (int i = 10; i > 0; i -= 4) {
System.out.print(i + " ");
}10 6 210 6 2 -26 210 6
Show the answer
i takes 10, 6, 2. The next update makes it -2, and -2 > 0 is false, so the loop stops before printing it. Updates can step by any amount, up or down.
Counting the passes
for (int i = 0; i < n; i++) runs exactly n times (0 to n-1). Switch < to <= and it runs n + 1 times, because both ends are included. i = 0; i <= 10 visits 0, 1, ..., 10: that's 11 values, not 10.
for (int i = 0; i < 5; i++) { } // 5x
for (int i = 0; i <= 5; i++) { } // 6x
for (int i = 1; i <= 5; i++) { } // 5xCount without running
How many times does for (int i = 3; i <= 7; i++) run?
Think about it, then reveal the answer
5 times: i = 3, 4, 5, 6, 7. Quick formula for <=: last minus first, plus one (7 - 3 + 1). Forgetting that +1 is the classic off-by-one.
Off by one
This is meant to print 1 to 10, but i < 10 stops when i is 10, so 10 never prints. The same bug in reverse: i > 1 in a countdown never prints 1. Check both ends: where does it start, and is the last value included?
// meant: 1 to 10
for (int i = 1; i < 10; i++) {
System.out.println(i);
} // stops at 9! use i <= 10Hands off the counter
The body ALSO changes i. What prints?
int sum = 0;
for (int i = 0; i < 8; i++) {
sum += i;
i++;
}
System.out.println(sum);2812166
Show the answer
i is incremented twice per pass: once in the body, once in the update. So the body sees i = 0, 2, 4, 6, and sum = 0 + 2 + 4 + 6 = 12. Changing the loop variable inside the body makes loops hard to read; avoid it.
Scope and optional parts
A variable declared in the header (int i) exists only inside the loop. And all three parts are optional: for (;;) has no condition, so it loops forever (until a break or return).
for (int i = 0; i < 3; i++) { }
// i doesn't exist here
for (;;) {
// runs until break/return
}In real projects
Off-by-one errors cause pagination that shows 11 items per page, reports that skip the last day of the month, and batch jobs that never process the final record. Code reviewers check loop boundaries first, and good unit tests always include the edge cases: empty input, one item, exactly the limit.
Key takeaways
- Order: init, check, body, update, check, body, update...
- for (int i = 0; i < n; i++) runs exactly n times
- A variable declared in the header only exists inside the loop
- All three parts are optional: for (;;) loops forever
💡 A for header is a recipe card: 'start here, keep going while this is true, take this step each time'.
Off-by-one errors are also called "fencepost errors": a 30 m fence with a post every 10 m needs 4 posts, not 3. Count the gaps and the posts separately!
Practice questions
What does this print?
for (int i = 1; i <= 10; i += 3) {
System.out.print(i + " ");
}- 1 4 7
- 1 4 7 10
- 4 7 10
- 1 4 7 10 13
Check your answer
1 4 7 10. i takes 1, 4, 7, 10. Then it becomes 13, 13 <= 10 is false, and the loop stops.
How many times does the body of for (int i = 0; i <= 10; i++) run?
- 10
- 11
- 9
- 12
Check your answer
11. It runs for i = 0, 1, ..., 10. That's 11 values because both ends are included.