Topic 2.5
while and do-while Loops
In one line
A while loop repeats a block as long as a condition stays true, checking the condition before each pass, so it may run zero times. A do-while checks after each pass, so its body always runs at least once.
Think of it like this
Eating soup. While there is soup in the bowl, take a spoonful. You check the bowl before each spoonful, and if it was empty from the start you never pick up the spoon. A do-while is tasting food while cooking: you taste first, then decide whether it needs more salt and another taste.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Loop
- A piece of code that repeats.
- Iteration
- One pass through the loop body.
- Loop condition
- The
booleantest that decides whether the loop runs (again). - Loop variable
- A variable whose value changes each iteration and is used in the condition, such as a counter.
- Infinite loop
- A loop whose condition never becomes false, so it repeats forever (until the program is stopped).
- Pre-test loop
- A loop that checks its condition before each iteration (
while,for). - Post-test loop
- A loop that checks its condition after each iteration (
do-while). - Sentinel
- A special value that signals 'stop', such as
0at the end of a list of numbers or-1for 'not found'.
Step by step
01Your first while loop
Three parts make a counting loop work: a starting value (int count = 1), a condition (count <= 3), and a change inside the body (count++). Leave out any one and the loop either never runs or never stops.
Trace it: count is 1, 1 <= 3 is true, print, count becomes 2. Then 2, then 3. Then count is 4, 4 <= 3 is false, the loop ends.
int count = 1;
while (count <= 3) {
System.out.println("Count: " + count);
count++;
}
System.out.println("Done, count is now " + count);02The flow of a pre-test loop
The condition sits at the door. Each time around, Java asks the question again. This is why a while can run zero times: if the answer is no at the start, the body is skipped completely.
03When you don't know the count: digits of a number
How many digits does 90210 have? You don't know how many times to loop, but you know when to stop: when nothing is left. Each pass removes the last digit with / 10 (integer division, Topic 1.7) and % 10 gives that digit.
This 'peel off the last digit' loop is one of the most common patterns in coding interviews. You'll use it again in Topic 2.10.
int n = 90210;
int digits = 0;
int sum = 0;
while (n > 0) {
sum += n % 10; // last digit
n /= 10; // drop the last digit
digits++;
}
System.out.println(digits + " digits, sum " + sum); // 5 digits, sum 1204do-while: body first, question second
A do-while puts the check at the bottom. The body runs, then the condition decides whether to go round again. Even when the condition is false from the start, the body runs once.
That fits 'do something, then decide whether to repeat' tasks: show a menu and repeat until the user picks Quit, retry an operation until it succeeds, or roll a die until you get a six.
int x = 10;
while (x < 5) {
System.out.println("while body"); // never runs
}
do {
System.out.println("do-while body"); // runs once
} while (x < 5);05Scope: what the condition can see
The do body is a block, and variables declared in a block die at its closing brace (Phase 3 covers scope in depth). The while (...) at the bottom is outside that block, so it can't see them.
Declare the variable before the do if the condition needs it.
int i = 0;
do {
int next = i + 1;
i = next;
} while (next < 5); // error: cannot find symbol: variable next
// Fixed
int j = 0;
int next2;
do {
next2 = j + 1;
j = next2;
} while (next2 < 5);06Infinite loops: deliberate and accidental
Accidental: forgetting the count++, changing the wrong variable, or a stray semicolon (while (count <= 3); loops forever on an empty body). The program hangs and uses a full CPU core. Stop it with Ctrl+C.
Deliberate: while (true) with a break or return inside, for loops whose exit point is in the middle (Topic 2.8). Servers and game loops are built like this.
The compiler checks constant conditions. Code after a while (true) with no break can never run, so it is an unreachable statement error. That rule keeps you from writing cleanup code that silently never happens.
07Under the hood: a jump back
Bytecode has no loop instruction. A loop is a conditional jump that exits, plus a goto that jumps back. The javap listing below is a counting loop: instruction 6 leaves the loop when i > n, instruction 16 jumps back to the test at 4.
When a loop runs many thousands of times, the JIT compiler notices (it counts back-edges, the jumps back to the top) and compiles the method to machine code, even switching the running loop over mid-iteration. That's on-stack replacement (OSR), and it's why a quick timing of a loop's first few runs says little about its real speed.
Try it yourself
- 1
Trace before you run
In 'The Collatz sequence', change
nto 7. On paper, write the sequence until you reach 1. Then run it and compare (it takes 16 steps and climbs to 52). - 2
Make it infinite, then fix it
In 'Counting with while', delete
count++. Run it, watchCount: 1scroll forever, and stop it (Ctrl+C in a terminal, or the stop button in the browser runner). Put the line back. - 3
while vs do-while
In 'do-while runs at least once', change the
do-whileto awhilewith the same condition. Predict whether anything prints, then run.
Code & diagrams
Expected output
Count: 1
Count: 2
Count: 3
After the loop, count = 4
A while loop can run zero timesReversed is 1209, not 01209: an int has no leading zeros.
Expected output
Number: 90210
Digits: 5
Sum of digits: 12
Reversed: 1209Nobody has proved this loop ends for every starting number (the Collatz conjecture), but it has for every number ever tried.
Expected output
6 -> 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
Reached 1 in 8 stepsExpected output
do-while body ran with x = 10
Attempt 1: failed
Attempt 2: failed
Attempt 3: successThe 'rule of 72' predicts 72 / 7 = about 10.3 years; the loop gives the exact whole-year answer.
Expected output
Doubled after 11 years: 2104.85Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Use a body variable in the do-while condition
Declare next inside the do block and test it in while (next < 5).
public class Main {
public static void main(String[] args) {
int i = 0;
do {
int next = i + 1;
i = next;
} while (next < 5);
}
}Break #2
Write code after an endless loop
Put a println after while (true) { ... } with no break inside.
public class Main {
public static void main(String[] args) {
while (true) {
System.out.println("x");
}
System.out.println("after");
}
}Break #3
A semicolon after while
Write while (count <= 3); followed by the block.
Myth vs fact
Myth
A while loop always runs at least once.
Fact
That's do-while. A while checks first and may run zero times.
Myth
while (true) is always a bug.
Fact
It's the standard shape for loops that exit from the middle with break or return, like menus, servers and retry loops.
Myth
Loops are slow in Java because it's interpreted.
Fact
Hot loops are JIT-compiled to machine code (even mid-run, via on-stack replacement), and the JIT unrolls and vectorises simple ones.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
JLS 14.22 defines 'can complete normally' rules:
while (true)without a reachablebreakcannot complete normally, so following statements are unreachable;while (false)makes its body unreachable. Note the asymmetry withif (false), which is allowed so you can write debug flags. - ▸
The JIT inserts safepoint polls at loop back-edges so the GC can pause threads. Counted
intloops may have the poll removed for speed, which historically caused long time-to-safepoint pauses; since JDK 10, loop strip mining splits long counted loops into chunks so polls stay frequent without slowing the inner loop. - ▸
A busy-wait like
while (!flag) {}on a plain (non-volatile) field may never see another thread's update: the JIT is allowed to hoist the read out of the loop. That's a memory-model issue, covered in the concurrency phase. Usevolatile, anAtomicBoolean, or proper blocking instead. - ▸
do-whilecompiles to a body followed by a conditional jump back, which is the natural shape for the CPU;javacplaces awhiletest at the top, and the JIT usually rotates it to the bottom (loop inversion) so each iteration costs one jump.
Remember this
- 1
while (condition) { body }checks the condition; if it'strueit runs the body, then checks again, and so on. As soon as the check isfalse, the loop ends and the program continues after it. If the condition is false the first time, the body runs zero times. - 2
do { body } while (condition);runs the body first and checks afterwards, so the body runs at least once. Note the semicolon after the closing bracket. A variable declared inside thedobody can't be used in its condition, because the body's block has already ended. - 3
Every loop needs something inside it that eventually makes the condition false: a counter that increases, input that runs out, a value that converges. Without that, you get an infinite loop.
while (true)is a deliberate infinite loop that you leave withbreak(Topic 2.8) orreturn. - 4
Use
whilewhen you don't know in advance how many times to repeat: until a number reaches 1, until the digits run out, until a search finds its target. When you know the count (do it 10 times, visit every array index), theforloop in Topic 2.6 is clearer. - 5
The compiler knows constant conditions.
while (false) { ... }is anunreachable statementerror, and code after awhile (true)loop with nobreakis also unreachable, so it's rejected. - 6
In bytecode a
whileis a conditional jump at the top (or bottom) plus agotoback. A loop that runs many times gets compiled to machine code by the JIT, and long-running loops are even swapped to compiled code mid-run (on-stack replacement).
Explain it without notes
What is the difference between while and do-while? Give a situation suited to each.
What three things does a counting while loop need, and what goes wrong if each is missing?
Why is code after while (true) { ... } with no break a compile error?
When would you choose a while loop over a for loop?
Practice
Using a while loop, print the powers of 2 that are less than 100, on one line separated by spaces.
Using a while loop, check whether 12321 is a palindrome number (reads the same backwards).
Using a do-while loop, print the numbers from 5 down to 1, then Lift off!.
Trade-offs
- ↔
whilekeeps the loop condition clear when the count is unknown, but the start and update are scattered across lines, making off-by-one and forgotten-update bugs easier than in afor. - ↔
do-whileis the right tool for 'at least once', but it is rare in real code; many teams preferwhile (true)with abreak, which puts the exit test wherever it naturally belongs.
Done when you can
Done when you can write a while loop with a start, a condition and an update, and trace it on paper.
Done when you can explain when a do-while is the right choice.
Done when you can write the 'peel off the last digit' loop from memory.
Done when you can recognise and fix an infinite loop and an unreachable-statement error.
Done when you can explain that a loop is a conditional jump plus a goto in bytecode, and what OSR is.