Skip to main content
Java beginner Lesson 6 of 58

Control Flow in Java

Master Java's decision-making and looping constructs — if/else, switch expressions, for/while/do-while loops, break, and continue.

Control flow determines the order in which statements execute. By default Java runs top to bottom — conditionals and loops let you branch and repeat. Mastering these constructs is what lets you write programs that make decisions, process collections of data, and respond to different inputs.

if / else

The if/else chain is the most fundamental decision-making tool. Java evaluates each condition in order and executes the first branch that is true. Use else if to express mutually exclusive ranges or categories, and always end with else to handle the unexpected.

int score = 82;

if (score >= 90) {
    System.out.println("Grade: A");
} else if (score >= 80) {
    System.out.println("Grade: B");
} else if (score >= 70) {
    System.out.println("Grade: C");
} else {
    System.out.println("Grade: F");
}
// Grade: B

Curly braces are optional for single-statement bodies, but always use them — omitting them is a common source of bugs.

Nested if

When multiple conditions must all be true, you can nest if blocks. Keep nesting shallow — deep nesting is hard to read and usually a sign that a compound condition or early return would be cleaner.

int age = 20;
boolean hasLicense = true;

if (age >= 18) {
    if (hasLicense) {
        System.out.println("Can drive");
    } else {
        System.out.println("Old enough, but no license");
    }
} else {
    System.out.println("Too young to drive");
}

When nesting gets deep, flatten with compound conditions:

if (age >= 18 && hasLicense) {
    System.out.println("Can drive");
}

switch Statement

The classic switch statement is designed for comparing a single value against a list of constants. It is cleaner than a long if-else chain when you have many discrete cases, and communicates intent more directly — you are routing on a value, not evaluating complex conditions.

int day = 3;
String name;

switch (day) {
    case 1:
        name = "Monday";
        break;
    case 2:
        name = "Tuesday";
        break;
    case 3:
        name = "Wednesday";
        break;
    case 6:
    case 7:
        name = "Weekend";
        break;
    default:
        name = "Unknown";
}
System.out.println(name); // Wednesday

break is required — without it, execution falls through to the next case.

switch Expression (Java 14+)

The modern switch expression is more concise, does not fall through, and can be used directly as a value. It also forces you to handle all possible cases — the compiler will warn if a case is missing, which prevents logic gaps.

int day = 3;
String name = switch (day) {
    case 1 -> "Monday";
    case 2 -> "Tuesday";
    case 3 -> "Wednesday";
    case 4 -> "Thursday";
    case 5 -> "Friday";
    case 6, 7 -> "Weekend";
    default -> throw new IllegalArgumentException("Invalid day: " + day);
};
System.out.println(name); // Wednesday

switch expressions can also use yield for multi-statement cases:

String result = switch (score / 10) {
    case 10, 9 -> "A";
    case 8     -> "B";
    case 7     -> "C";
    default    -> {
        System.out.println("Calculating...");
        yield score >= 60 ? "D" : "F"; // yield returns the value from a block
    }
};

switch works with int, String, char, enum, and (Java 21+) patterns.

for Loop

The for loop is used when you know in advance how many iterations to run. Its three-part header — init, condition, update — keeps all loop control in one line, making it easy to scan at a glance.

// Basic: init; condition; update
for (int i = 0; i < 5; i++) {
    System.out.print(i + " ");
}
// 0 1 2 3 4

// Count down
for (int i = 10; i > 0; i -= 2) {
    System.out.print(i + " ");
}
// 10 8 6 4 2

// Multiple variables
for (int i = 0, j = 10; i < j; i++, j--) {
    System.out.println("i=" + i + " j=" + j);
}

Enhanced for (for-each)

The for-each loop iterates over any array or Iterable without managing an index. It is cleaner and less error-prone for the common case of “do something for every element.” Use the index-based for only when you actually need the index.

int[] numbers = {10, 20, 30, 40, 50};
for (int n : numbers) {
    System.out.print(n + " ");
}
// 10 20 30 40 50

String[] fruits = {"apple", "banana", "cherry"};
for (String fruit : fruits) {
    System.out.println(fruit.toUpperCase());
}

while Loop

The while loop is used when you do not know in advance how many iterations are needed — the loop runs as long as a condition stays true. It is the right tool for reading input until a sentinel value, polling until a resource is ready, or any open-ended repetition.

int n = 1;
while (n <= 10) {
    System.out.print(n + " ");
    n++;
}
// 1 2 3 4 5 6 7 8 9 10

// Reading input until sentinel value
Scanner sc = new Scanner(System.in);
int sum = 0;
System.out.println("Enter numbers (0 to stop):");
int input = sc.nextInt();
while (input != 0) {
    sum += input;
    input = sc.nextInt();
}
System.out.println("Sum: " + sum);

do-while Loop

The do-while loop guarantees that the body executes at least once, then checks the condition. This is the natural fit for input validation — you always need to prompt the user once before you can check whether their answer is valid.

// Input validation — always ask at least once
Scanner sc = new Scanner(System.in);
int age;
do {
    System.out.print("Enter age (1-120): ");
    age = sc.nextInt();
} while (age < 1 || age > 120);
System.out.println("Valid age: " + age);

// Countdown that always runs
int count = 5;
do {
    System.out.println("T-minus " + count);
    count--;
} while (count > 0);
System.out.println("Liftoff!");

break and continue

break and continue give you fine-grained control inside loops without needing a flag variable. They make the intent explicit: either stop the loop entirely or skip the rest of the current iteration.

break — Exit the Loop Early

// Find first even number — stop as soon as we find it
int[] nums = {7, 3, 9, 4, 11, 2};
int firstEven = -1;
for (int n : nums) {
    if (n % 2 == 0) {
        firstEven = n;
        break; // stop searching — no need to look further
    }
}
System.out.println("First even: " + firstEven); // 4

continue — Skip to the Next Iteration

// Print only odd numbers — skip evens without nesting an if block
for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) continue; // skip even numbers
    System.out.print(i + " ");
}
// 1 3 5 7 9

Labelled break — Exit an Outer Loop

A regular break only exits the innermost loop. A labelled break exits any enclosing loop you name. This is cleaner than using a boolean flag when searching a 2D structure.

outer:
for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
        if (i == 2 && j == 2) {
            System.out.println("Found at (" + i + "," + j + ")");
            break outer; // exits both loops immediately
        }
    }
}

Projects

Number Guessing Game

import java.util.Scanner;

public class GuessingGame {
    public static void main(String[] args) {
        int secret = (int)(Math.random() * 100) + 1; // random number 1-100
        Scanner sc = new Scanner(System.in);
        int attempts = 0;
        int guess;

        System.out.println("Guess the number between 1 and 100!");

        // do-while ensures the player guesses at least once
        do {
            System.out.print("Your guess: ");
            guess = sc.nextInt();
            attempts++;

            if      (guess < secret) System.out.println("Too low!");
            else if (guess > secret) System.out.println("Too high!");
            else                     System.out.println("Correct in " + attempts + " attempts!");

        } while (guess != secret);

        sc.close();
    }
}

Multiplication Tables

public class MultiplicationTable {
    public static void main(String[] args) {
        // Nested loops — outer controls rows, inner controls columns
        for (int i = 1; i <= 10; i++) {
            for (int j = 1; j <= 10; j++) {
                System.out.printf("%4d", i * j);
            }
            System.out.println();
        }
    }
}

Pattern Printing

public class Patterns {
    public static void main(String[] args) {
        int n = 5;

        // Right triangle — inner loop runs one more time per outer iteration
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++) System.out.print("* ");
            System.out.println();
        }
        // *
        // * *
        // * * *
        // * * * *
        // * * * * *

        System.out.println();

        // Pyramid — spaces decrease, stars increase each row
        for (int i = 1; i <= n; i++) {
            for (int j = i; j < n; j++)  System.out.print(" ");
            for (int j = 1; j <= 2*i-1; j++) System.out.print("*");
            System.out.println();
        }
        //     *
        //    ***
        //   *****
        //  *******
        // *********
    }
}

Frequently Asked Questions

When should I use switch instead of if-else?
Use switch when you're comparing one variable against multiple constant values. It's cleaner than a long if-else chain. Java 14+ switch expressions are especially concise and force you to handle all cases.
What is the difference between while and do-while?
A while loop checks the condition before running — it may never execute. A do-while loop runs the body first, then checks — it always executes at least once. Use do-while when you need to run the body at least one time (e.g., input validation).
What does break do in a nested loop?
break exits only the innermost loop it's inside. To break out of an outer loop, use a labelled break: label: for(...) { for(...) { break label; } }