☕ Java
do-while Loop
The do-while loop is Java's only post-test loop — the condition is evaluated after the body executes, which guarantees the body runs at least once regardless of the condition's initial value. This property makes do-while the natural fit for scenarios where the first execution must happen before the first check: menu-driven programs, input validation, digest computation, and game turns. This entry covers syntax, when to use do-while over while, input validation patterns, and the subtle differences that matter in practice.
Syntax and the Post-Test Guarantee
The do-while loop places the body before the condition. The keyword do opens the body block; the closing brace is followed by while (condition) and a mandatory semicolon. The semicolon is required by the Java grammar and its absence is a compile error — unlike the for and while loops which have no semicolon after the closing brace.
The fundamental guarantee: the body always executes at least once. After the first execution the condition is evaluated, and if it is true the loop repeats. This post-test structure means the body can freely use results computed in the first pass when deciding whether to continue. With a regular while loop you would need to duplicate the body's first execution (or extract it into a method) to achieve the same effect — a pattern called "loop and a half" that do-while solves cleanly.
Java
// ── Syntax ────────────────────────────────────────────────────────────
do {
// body — ALWAYS executes at least once
} while (condition); // ← semicolon is REQUIRED
// ── Body always runs even when condition starts false ─────────────────
int x = 100;
do {
System.out.println("Executed once: x=" + x);
x++;
} while (x < 5); // condition is false from the start
// Output: "Executed once: x=100"
// The body still runs exactly once
// ── Compare with while ────────────────────────────────────────────────
// while skips body when condition is initially false:
int y = 100;
while (y < 5) {
System.out.println("This never prints");
}
// ── Execution flow ────────────────────────────────────────────────────
// 1. Execute body
// 2. Evaluate condition
// 3. If true → back to step 1
// 4. If false → exit loop
// ── Equivalent for loop ───────────────────────────────────────────────
// This for loop also guarantees one execution by initialising
// a flag and using it in the condition — verbose compared to do-while
boolean firstPass = true;
for (int i = 0; firstPass || i < 5; i++, firstPass = false) {
System.out.println(i);
}
// do-while is cleaner for this patternInput Validation — The Classic Use Case
Input validation is the canonical use case for do-while. The requirement is: ask for input, validate it, and if invalid ask again. The first prompt must always happen — there is no way to check validity before the first input has been collected. A while loop would require either duplicating the input-reading code before the loop or using a priming read idiom. Do-while expresses the intent directly: do (get input) while (input is invalid).
This pattern is robust and clear. The prompt and read are inside the loop body, the validation is in the condition, and the loop guarantees the user is always asked at least once. After the loop exits, the variable holds a valid value and can be used unconditionally.
Java
// ── Pattern 1: Numeric range validation ──────────────────────────────
Scanner scanner = new Scanner(System.in);
int age;
do {
System.out.print("Enter age (1-120): ");
while (!scanner.hasNextInt()) {
System.out.println("Not a number. Try again.");
scanner.next();
System.out.print("Enter age (1-120): ");
}
age = scanner.nextInt();
if (age < 1 || age > 120) {
System.out.println("Age must be between 1 and 120.");
}
} while (age < 1 || age > 120);
System.out.println("Valid age: " + age);
// ── Pattern 2: Password confirmation ─────────────────────────────────
String password;
String confirm;
do {
System.out.print("Enter password: ");
password = scanner.next();
System.out.print("Confirm password: ");
confirm = scanner.next();
if (!password.equals(confirm)) {
System.out.println("Passwords do not match. Try again.");
}
} while (!password.equals(confirm));
System.out.println("Password set successfully.");
// ── Pattern 3: Y/N prompt ────────────────────────────────────────────
char response;
do {
System.out.print("Continue? (Y/N): ");
response = scanner.next().toUpperCase().charAt(0);
if (response != 'Y' && response != 'N') {
System.out.println("Please enter Y or N.");
}
} while (response != 'Y' && response != 'N');
if (response == 'Y') {
System.out.println("Continuing...");
} else {
System.out.println("Stopping.");
}Menu-Driven Programs
A menu-driven program displays options, reads the user's choice, executes the selected action, and then returns to the menu — repeating until the user chooses to exit. This is a perfect do-while scenario: the menu must be displayed before the first choice is known, and after each action the loop restarts and displays the menu again. The loop exits when the user selects the exit option.
The do-while structure maps directly to the requirement: do (show menu, get choice, execute action) while (choice is not exit). The choice variable is declared before the loop, used in the body, and its final value — the exit choice — is the reason the condition becomes false.
Java
// ── Menu-driven calculator ───────────────────────────────────────────
Scanner scanner = new Scanner(System.in);
int choice;
double result = 0;
do {
System.out.println("
=== Calculator ===");
System.out.println("1. Add");
System.out.println("2. Subtract");
System.out.println("3. Multiply");
System.out.println("4. Divide");
System.out.println("5. Show result");
System.out.println("0. Exit");
System.out.print("Choice: ");
choice = scanner.nextInt();
switch (choice) {
case 1 -> {
System.out.print("Enter number: ");
result += scanner.nextDouble();
System.out.println("Result: " + result);
}
case 2 -> {
System.out.print("Enter number: ");
result -= scanner.nextDouble();
System.out.println("Result: " + result);
}
case 3 -> {
System.out.print("Enter number: ");
result *= scanner.nextDouble();
System.out.println("Result: " + result);
}
case 4 -> {
System.out.print("Enter number: ");
double divisor = scanner.nextDouble();
if (divisor == 0) {
System.out.println("Cannot divide by zero.");
} else {
result /= divisor;
System.out.println("Result: " + result);
}
}
case 5 -> System.out.println("Current result: " + result);
case 0 -> System.out.println("Goodbye!");
default -> System.out.println("Invalid choice.");
}
} while (choice != 0); // loop until user chooses exitAlgorithmic Use Cases
Beyond interactive programs, do-while appears in several important algorithms. Newton's method for computing square roots iterates until the estimate converges — at least one estimate must be computed before convergence can be checked. Hash table probing tries a slot, then checks if the correct entry was found. Number-theoretic algorithms such as computing the Collatz sequence always perform at least one step.
These cases share the characteristic that the first action must precede the first check, and do-while expresses this requirement without the awkwardness of duplicated code or extra variables.
Java
// ── Newton's method — square root approximation ──────────────────────
// At least one estimate must be produced before checking convergence
double target = 2.0;
double estimate = target / 2.0;
double precision = 1e-10;
do {
double improved = 0.5 * (estimate + target / estimate);
double error = Math.abs(improved - estimate);
estimate = improved;
// Check convergence AFTER computing — not before
if (error < precision) break;
} while (true); // or while (Math.abs(estimate*estimate - target) > precision)
System.out.printf("sqrt(2) ≈ %.10f%n", estimate);
// Output: sqrt(2) ≈ 1.4142135624
// ── Collatz sequence ──────────────────────────────────────────────────
// At least one step always occurs (n changes before checking n==1)
int n = 27;
int steps = 0;
do {
if (n % 2 == 0) {
n /= 2;
} else {
n = 3 * n + 1;
}
steps++;
} while (n != 1);
System.out.println("Steps to reach 1: " + steps); // 111
// ── Random number game (guess the number) ────────────────────────────
int secret = (int)(Math.random() * 100) + 1;
int guess;
int attempts = 0;
do {
System.out.print("Guess (1-100): ");
guess = scanner.nextInt();
attempts++;
if (guess < secret) System.out.println("Too low");
else if (guess > secret) System.out.println("Too high");
else System.out.println("Correct!");
} while (guess != secret);
System.out.println("Solved in " + attempts + " attempts.");do-while vs while — Choosing the Right Loop
The choice between while and do-while comes down to one question: must the body execute before the condition can be evaluated? If yes, do-while is the correct choice. If the condition can be evaluated meaningfully before any body execution, while is correct. In practice, do-while is less common than while because most loops benefit from checking the condition first to handle the empty case correctly. Do-while is specifically for situations where the empty case (zero executions) is impossible or wrong by design.
There is no situation where do-while is strictly necessary — every do-while loop can be rewritten as a while loop with duplicated code or a boolean flag. The value of do-while is expressiveness: it communicates "at least one execution is guaranteed" directly in the code structure, making the intent obvious to the reader.
Java
// ── Decision guide ───────────────────────────────────────────────────
//
// Question: Can the condition be checked BEFORE the first execution?
//
// YES — condition can be pre-checked:
// Use while (or for if count-controlled)
// Example: iterate over a list, process if non-empty
//
// NO — first execution must happen before condition makes sense:
// Use do-while
// Examples: get input, show menu, compute first estimate
// ── Same problem, both approaches ────────────────────────────────────
// while version — needs priming read (code before AND in loop)
System.out.print("Enter number (-1 to stop): ");
int num = scanner.nextInt(); // ← duplicated read
while (num != -1) {
process(num);
System.out.print("Enter number (-1 to stop): ");
num = scanner.nextInt(); // ← same read again
}
// do-while version — cleaner, no duplication
int num2;
do {
System.out.print("Enter number (-1 to stop): ");
num2 = scanner.nextInt();
if (num2 != -1) process(num2);
} while (num2 != -1);
// ── Refactoring: extract to a method instead ────────────────────────
// When logic is complex, extract to a method — both loops become clean
private int readNumber(Scanner sc) {
System.out.print("Enter number (-1 to stop): ");
return sc.nextInt();
}
// while with extracted read — no duplication
int value = readNumber(scanner);
while (value != -1) {
process(value);
value = readNumber(scanner);
}Related Topics in Control Statements
Control Statements
Control statements determine the flow of execution in a Java program. Without them, code executes line by line from top to bottom. Control statements allow the program to make decisions, repeat actions, and jump to different parts of the code based on conditions. Java provides three categories: selection statements (if, if-else, switch), iteration statements (for, while, do-while), and jump statements (break, continue, return).
if Statement
The if statement is the most fundamental control flow construct in Java. It evaluates a boolean expression and executes a block of code only if the expression is true. If the condition is false the block is skipped entirely and execution continues with the next statement after the if block.
if-else Statement
The if-else statement extends the basic if by providing an alternative block that executes when the condition is false. It guarantees that exactly one of two blocks always executes — either the if block (condition true) or the else block (condition false). The if-else-if chain extends this to choose among more than two alternatives.
Nested if
A nested if is an if statement placed inside the body of another if or else block. Nesting allows multi-level decision making — first check a broad condition, then refine with a more specific condition inside it. While nesting is sometimes necessary, deep nesting quickly reduces readability and should be refactored using guard clauses, logical operators, or extracted methods.