Java While and Do-While Loops
Repeat work without repeating source code. Learn when the condition is checked, what changes on each iteration, and how to explain exactly why a loop stops.
Before you start: review boolean decisions, switch menus, and Scanner input. Full source examples use the Java 21 runner. Predict first, run second, then change one starting value or boundary.
What you will be able to do
- Trace initialization, condition checks, body execution, and updates.
- Explain why while can run zero times and do-while starts with its body.
- Choose inclusive and exclusive boundaries deliberately.
- Keep a counter and an accumulated total separate.
- Explain what changes on every repeating path and why the loop stops.
- Process multiple menu commands without reading past the end of input.
A loop repeats work, not source code
Suppose a student needs three practice steps. You could write three println statements, but changing the number of steps would mean editing repeated code. A loop describes the repetition once. Each trip through its body is called an iteration. The changing step value tells this program which iteration it is processing.
Read while (step <= 3) as: before doing the next step, check whether step is still at most 3. If the answer is true, run the body. If it is false, leave the loop and continue after the closing brace. The condition is a boolean expression, just like an if condition, but while can return to that question repeatedly.
The four pieces work together: int step = 1 establishes the starting state; step <= 3 decides whether to enter; println performs the repeated work; step++ updates the state. The update is not supplied automatically by while. Without an appropriate change, a condition that started true may remain true indefinitely.
Main.java · Repeat three practice steps
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Practice step 1
Practice step 2
Practice step 3
Next step value: 4
Trace the condition before every iteration
For step 1, the comparison 1 <= 3 is true, so the first message prints and the update changes step to 2. The next comparison uses 2, not the original value 1. After the third message, step becomes 4. Java checks 4 <= 3, gets false, and skips the body instead of printing a fourth practice step.
That final unsuccessful check is part of the execution, even though it prints nothing. The statement after the loop displays 4 because the counter still exists in the enclosing method and was updated before the last check. Three completed iterations do not imply that the counter must finish at 3.
Pause before editing and predict the effect of replacing <= with <. Starting at 1, step < 3 accepts 1 and 2 but rejects 3, so only two practice messages print. Choose the boundary from the task: include step 3 when it is a valid step, rather than changing the comparison until one sample output looks plausible.
Trace the three-step loop without running it
- step is 1: condition true, print 1, update to 2.
- step is 2: condition true, print 2, update to 3.
- step is 3: condition true, print 3, update to 4.
- step is 4: condition false, skip the body and print the final counter value.
Now use a starting value of 3. With the original inclusive boundary, how many iterations should run?
while may execute zero times
A while condition is tested before the first body execution. If there are already zero remaining tasks, remaining > 0 is false immediately. The body is never entered, the decrement is never reached, and the final message still prints. This is useful when there might genuinely be nothing to process.
Try remaining = 1 in this example. It prints the task message once, decrements to zero, then fails the next check. Try remaining = 3 to get three task messages. These small changes show that the start value and boundary jointly determine the number of iterations.
A loop is not a replacement for input validation. In this small demonstration, a negative remaining value also skips the body; that does not prove negative task counts are acceptable data. If the domain forbids negatives, reject them before the loop, then let the loop focus on processing valid work.
Main.java · A false first check skips the body
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Nothing left to process.
The update must move toward an exit
For a positive countdown, remaining-- subtracts one on each iteration. The state moves from 3 to 2 to 1 to 0, where remaining > 0 becomes false. Ask a concrete question when reviewing a loop: which value changes, in which direction, and what state makes the next condition false?
Changing the decrement to an increment would move away from zero instead of finishing the intended countdown. With int values, overflow can eventually wrap the counter, but relying on billions of unintended iterations is not a termination strategy. Keep bounds realistic and select an update that implements the actual task.
Different loops make progress in different ways. A counter approaches a boundary; an input loop consumes another line; a menu flag becomes false when the user chooses quit. If a branch repeats without updating state, consuming input, or exiting, inspect it carefully. A valid-input path can work while a rejected-input path gets stuck.
Main.java · Move toward the stopping boundary
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Tasks remaining: 3
Tasks remaining: 2
Tasks remaining: 1
Finished with 0 tasks remaining.
A counter measures progress; an accumulator remembers results
The day variable tells the loop which day it is processing. totalMinutes remembers the sum across all processed days. These are separate jobs. In this example, the daily minutes are derived from day solely to keep the arithmetic visible: 10, then 20, then 30. Their accumulated total is 60, not the final day value 4.
Initialize totalMinutes before the loop so each iteration adds to the previous result. Declaring and resetting it to zero inside the body would discard earlier contributions. minutesToday, on the other hand, is temporary work for the current iteration, so declaring it inside the body communicates its narrower role.
Read totalMinutes += minutesToday as adding today's amount to the running total. Trace it from 0 to 10 to 30 to 60. Keep counting and summing separate, and choose numeric types with enough range for the intended data. A loop does not protect int arithmetic from overflow just because each individual addend is small.
Main.java · Keep the counter and total separate
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Day 1: 10 minutes
Day 2: 20 minutes
Day 3: 30 minutes
Total: 60 minutes
Explain where the total comes from
The total starts at 0. Day 1 adds 10, making 10. Day 2 adds 20, making 30. Day 3 adds 30, making 60. The counter then becomes 4, but 4 is not added to the total. The failed check ends repetition before another contribution is calculated.
do-while runs its body before asking whether to repeat
A do-while puts its condition after the body. Execution starts with do { ... }, then evaluates while (...). In the example, the starting remaining value is zero, yet the body prints once. The later check is false, so there is no second iteration. This is the essential difference from the earlier while example.
Use this structure when the first action is meaningful before any repeat decision, such as showing an initial preview and then checking whether another is needed. Do not use it for work that must only happen after a successful availability check. A forced first read from empty input can fail before the bottom condition ever has a chance to help.
Notice the semicolon after while (remaining > 0);. It is required for do-while. This is different from accidentally placing a semicolon after the condition of an ordinary while, which creates an empty loop body. Similar punctuation in two related structures can have very different effects.
Main.java · do-while enters before checking
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Body entered with remaining = 0
Loop finished.
Choose the first-check position from the task
The attempt example shows a do-while that repeats more than once. The body prints the current attempt and increments it before the bottom check. Attempts 1, 2, and 3 print; the update to 4 then makes the condition false. A post-test loop still needs a correct update and stopping rule.
With this starting value and boundary, a while version would produce the same output. To see the real distinction, change the start to 4: a while (attempt <= 3) would enter zero times, while this do-while prints attempt 4 once. The syntax choice matters most when the condition could be false at entry.
Choose while when permission or available work must be checked before every execution, including the first. Choose do-while when the first action is unconditional and the condition decides only whether to repeat. Do not pick do-while merely because it can save an initial assignment; the first action still needs to be safe.
Main.java · Update before the next do-while check
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Preview attempt 1
Preview attempt 2
Preview attempt 3
Next attempt value: 4
Input loops need both a stop command and an end-of-input policy
A sentinel is a special input value that ends processing instead of being treated as ordinary data. Here the exact lowercase word stop is the sentinel. Other lines print with Read: in front of them. After reading stop, running becomes false and the loop exits before reading the following help line.
The condition running && scanner.hasNextLine() also handles input that ends without a stop word. Short-circuit evaluation means that once running is false, the availability check is not needed. Each entered iteration reads exactly one whole line, so the input position advances even when the command is not the sentinel.
The website runner receives all standard input before execution; it is not a live terminal waiting for typing after Run. Expand the prefilled input and edit the lines before running. In an actual terminal hasNextLine may wait for more input; in this finite runner it reaches end-of-input after the supplied lines. The final message distinguishes that event from an explicit stop command.
Main.java · Read until stop or end of input
Predict the result, edit Main.java, then run your program.
Standard input · prefilled example
Select Run code to compile and execute this program.
Read: learn
Read: practice
Stop command received.
Try the two different exits
Delete stop from the input: help is now read too, and the final message becomes Input ended. Put stop first: no Read lines print. The sentinel is consumed but not treated as ordinary work. This example accepts the exact lowercase stop; the lab adds deliberate case normalization.
Leaving a switch does not necessarily leave its surrounding loop
A switch can sit inside a loop. In the example, round 1 enters the first colon case. Its unlabelled break leaves the nearest enclosing switch, not the outer while. Execution then prints Round finished: 1, increments round, and proceeds to the next loop check.
Round 2 selects default, prints its selection and footer, then increments to 3. Only the false round <= 2 condition stops the while. This distinction matters when extending a one-command menu: adding a break inside a quit case does not by itself mean quit the entire menu loop.
The lab uses a running flag and arrow rules instead. Its quit rule sets the flag to false, and the next while condition stops repetition. return would leave main immediately and skip any shared session summary afterward. The next lesson covers break and continue more broadly; here the important skill is identifying which structure controls the repetition.
Main.java · A switch break is not a loop exit
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
First selection
Round finished: 1
Another selection
Round finished: 2
All rounds finished.
Test the empty, smallest, normal, and stopping cases
For a counter loop, start with a case that should run zero times, then one that should run exactly once, then a short normal run. Check the first and last printed values as well as the number of lines. These cases expose off-by-one mistakes much more clearly than a long output containing hundreds of repeated lines.
For an input loop, test empty input, one command, multiple commands, a sentinel first, a sentinel in the middle, and input ending without a sentinel. Rejected commands should consume their line and return to a meaningful next check. A loop that only advances after valid input can keep rejecting the same bad token forever.
Avoid intentionally running an unbounded print loop to prove that it is broken. Identify the missing progress by tracing it, then repair it with a small bounded test. The local Java sandbox has time and output limits, but a killed run is not a correct algorithm or a reliable way to produce a final result.
Repair exercise: include the final practice step
The task is to print practice steps 1, 2, and 3 exactly once, then print Done. This version compiles but misses a step. Predict its output, repair the boundary without adding another println, and test a one-step target too.
Main.java · Find the missing step
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Reveal the explained repair
The original < comparison rejects step 3 before its body runs. The inclusive <= boundary includes the intended final step. Keep step++ inside the body so each successful iteration makes progress. With target 1 the repair prints one step; with target 0 it prints only Done. Moving the update outside the loop would leave the condition unchanged during repetition and is not a valid repair.
Main.java · Repaired practice steps
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Practice step 1
Practice step 2
Practice step 3
Done.
Independent lab: build a repeating learning menu
Extend the previous lesson's menu into a repeating console session. Read one command per line, show recognized destinations, and keep processing until quit or end-of-input. Count only destinations actually shown. This previews menu routing; it does not navigate the website or change account data.
- Create one Scanner and a running flag before the loop. Repeat only while running is true and another input line exists.
- Read one whole line on every iteration, strip surrounding whitespace, and lowercase with Locale.ROOT.
- For learn or courses print Destination: Course roadmap; for practice print Destination: Practice exercises; for help or ? print Destination: Help guide. Count each of these once.
- A blank command prints Command cannot be blank. An unsupported command prints Unknown command. Both must consume the line and allow the next command to be processed.
- quit sets running to false without counting a destination. Do not read or process later supplied lines. Use arrow-style switch rules for command selection.
- After the loop print Goodbye. if quit was supplied, otherwise Input ended. Then print Destinations shown: followed by the recognized destination count. The summary must appear exactly once.
The prefilled input contains learn, PRACTICE with surrounding spaces, and quit on separate lines. Supply every line before Run; this runner is not a live terminal. Expected output:
Destination: Course roadmap
Destination: Practice exercises
Goodbye.
Destinations shown: 2
Main.java · Build your repeating menu
Predict the result, edit Main.java, then run your program.
Standard input · prefilled example
Select Run code to compile and execute this program.
Hints before the solution
Keep the Scanner, running flag, and destination count outside the loop. Combine the flag with hasNextLine in the condition. Read before branching so invalid commands still consume a line. quit changes the flag; recognized cases increment the count. Put the exit message and final count after the loop, not inside it.
Reveal the explained lab solution
Main.java · Repeating-menu solution
Predict the result, edit Main.java, then run your program.
Standard input · prefilled example
Select Run code to compile and execute this program.
The loop checks availability before reading, so empty input is safe. Each iteration consumes one line before choosing a branch; blank and unknown inputs therefore cannot keep the same unread line stuck at the front. Recognized destinations increment the accumulator once, while quit only changes the flag. No return is needed: after quit the next condition is false, leaving the shared summary reachable. If the input ends first, running stays true and the summary reports Input ended. This flag distinguishes two exit reasons, not whether the session had any valid commands.
Test changes and boundaries
Edit the input box for each test. Reset restores the original source and three-line input. Watch both the output messages and the final count: rejecting a command should not accidentally count a destination or prevent the next line from being read.
- Use the prefilled three lines: two destinations and Goodbye. must be followed by a count of 2.
- Try courses, help, and ? on separate lines without quit. Expect three destinations, Input ended., and a count of 3.
- Try a blank line, delete, then practice and quit. Expect two rejection messages, one destination, Goodbye., and a count of 1.
- Clear all input: expect Input ended. and count 0. Supply only quit: expect Goodbye. and count 0. These test different exit reasons.
- Try uppercase QUIT surrounded by spaces, followed by learn. The normalized quit must stop the loop; learn must not print or contribute to the count.
Common mistakes and how to diagnose them
The same line prints until the sandbox stops it
Trace the state after one iteration. A missing update, wrong-direction update, or unchanged flag can leave the repeat condition true. Repair the progress rule; increasing sandbox limits does not correct the loop.
The first or last item is missing
Check initialization together with < versus <= and the position of the update. Starting at 1 with step < 3 processes only 1 and 2. Trace zero, one, and three expected iterations before testing larger values.
The total only contains the last iteration
The accumulator may be reset inside the body. Initialize it once outside the loop, add each current contribution, and print the combined result afterward. Keep temporary per-iteration values inside when appropriate.
do-while processes an item when nothing is available
Its first body execution happens before the condition check. If processing requires data, use a pre-checking while or validate availability before that first action. do-while does not guarantee that an input read is safe.
The program cannot read another line
Check hasNextLine before nextLine, and supply all runner input before Run. Reaching the end of the supplied input is a normal exit path here, not a request for the browser runner to become a live terminal.
Choosing quit still starts another menu round
A break inside a nested switch leaves that switch, not its enclosing while. Set a flag tested by the loop, or choose another explicit loop exit strategy. Keep the intended shared summary outside the loop.
Frequently asked questions
What is an iteration?
One execution of the loop body. A while may have zero iterations, because its first condition check can fail. A do-while starts with its body before checking whether to repeat.
Does while change the counter automatically?
No. The condition only decides whether to enter. Your body must update the relevant state, consume input, or take an exit path. Check all repeating branches, not just the normal one.
Is do-while always better for menus?
No. It suits a first action that is safe and unconditional. This runner's menu must check finite input availability before reading, so a while with hasNextLine is clearer. A menu can also be built with do-while when the first read is protected appropriately.
Why is there a semicolon after do-while?
It is part of do { ... } while (condition); syntax. For an ordinary while, a semicolon immediately after while (condition) instead creates an empty body, which can cause a loop that never makes progress.
Does every loop need a numeric counter?
No. A flag, input availability, or another changing state can control repetition. The menu counts recognized destinations for its summary, but the running flag and input availability decide whether another iteration is allowed.
Explain the first check, every update, and the final exit
A while tests before the body; a do-while tests afterward. The comparison, starting state, and update work together to determine the iterations. Counters track progress, accumulators preserve results, and input loops need an explicit policy for both sentinel commands and end-of-input.
Before moving on, explain why the lab handles empty input safely, why a blank command cannot stall it, and why a switch break is not the same as ending a menu loop. Next: for loops, break, and continue.
Can you explain why the loop stops?
Answer all six questions and read the reasoning. Results are temporary on this page and do not save course progress.
References and related learning
These scenarios, explanations, examples, and exercises are original SovranCode material. Official references support the Java 21 language and input rules.
- Java 21 specification: while statements
- Java 21 specification: do statements
- Java 21 specification: break statements
- Scanner API: line availability and reading
Review one-command switch menus · Review finite Scanner input · Review conditions and updates · Java course roadmap.
Last updated: