Control Flow

Learning goals

Write conditional branches, loops, and switch expressions; choose the right construct for each task; and avoid classic control-flow bugs (missing breaks, unreachable code, accidental fall-through).


if / else

int score = 85;

if (score >= 90) {
    System.out.println("A");
} else if (score >= 80) {
    System.out.println("B");
} else {
    System.out.println("Below B");
}

Conditions must be boolean. No truthy/falsy like JavaScript:

// if (count) { }  // compile error
if (count > 0) { }

switch — classic and modern

Switch expression (JDK 14+, preferred)

String day = "MON";
int hours = switch (day) {
    case "MON", "TUE", "WED", "THU", "FRI" -> 8;
    case "SAT", "SUN" -> 0;
    default -> throw new IllegalArgumentException("Unknown: " + day);
};
  • -> avoids fall-through; no break needed.
  • Expression form returns a value (use yield in block cases if needed).
int code = switch (status) {
    case "OK" -> 200;
    case "ERROR" -> {
        logError();
        yield 500;
    }
    default -> 400;
};

Classic switch (legacy)

switch (day) {
    case "MON":
        System.out.println("Start week");
        break;  // required without ->
    case "FRI":
        System.out.println("Almost weekend");
        break;
    default:
        System.out.println("Other");
}

Fall-through without break executes the next case—often a bug.

Switch supports String, primitives (int, char, byte, short), enums, and sealed types (with pattern matching in newer JDKs).


for loop

for (int i = 0; i < 10; i++) {
    System.out.println(i);
}

Enhanced for (for-each)—read-only over iterables/arrays:

int[] nums = {3, 1, 4};
for (int n : nums) {
    System.out.println(n);
}

You cannot reassign the loop variable to change the array element’s slot semantics—use indexed for to mutate by index.


while and do-while

int n = 0;
while (n < 5) {
    n++;
}

int m = 0;
do {
    m++;
} while (m < 5);

do-while runs at least once. Use when the body must execute before the first check (e.g., menu prompts).


break and continue

for (int i = 0; i < 100; i++) {
    if (i % 2 == 0) continue;  // skip evens
    if (i > 10) break;         // exit loop
    System.out.println(i);
}

Labeled break (rare but useful for nested loops):

outer:
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (i * j > 2) break outer;
    }
}

Pattern matching in switch (JDK 21 preview/stable features)

Be aware of evolving syntax for type patterns:

Object obj = "hello";
String result = switch (obj) {
    case String s -> "String: " + s;
    case Integer i -> "Integer: " + i;
    case null -> "null";
    default -> "other";
};

Guarded patterns (case String s when s.length() > 5) refine matching—read JDK release notes when upgrading.


return and early exit

Methods can return early to reduce nesting:

public String findUser(String id) {
    if (id == null || id.isBlank()) {
        return "unknown";
    }
    // main lookup logic
    return lookup(id);
}

Common mistakes

  1. Assignment in condition: if (x = 5) — use ==.
  2. Switch fall-through in classic switch without break.
  3. Infinite loops: while (true) without break, or forgetting to update loop variable.
  4. Off-by-one: i <= arr.length when indexing 0..length-1.
  5. Modifying collection while foreach-ing — causes ConcurrentModificationException; use iterator.remove or collect then remove.

Practice checkpoint

  1. Rewrite with switch expression: map 1..5 to "one".."five", default "?".

    • Answer: switch (n) { case 1 -> "one"; ... default -> "?"; }
  2. Print first 5 odd numbers using a while loop.

    • Answer: Start i=1, while count<5 print and i+=2.
  3. What happens without break after case "A": in classic switch?

    • Answer: Execution falls through into the next case.
  4. When prefer do-while over while?

    • Answer: When body must run at least once before condition check.

Interview angles

  • “switch on String—how?” — Compiler uses hashCode/equals internally; null throws NPE.
  • “for vs enhanced for?” — Enhanced for is simpler and safe for read-only iteration; indexed for when you need index or mutation.
  • “Can switch replace if-else chains?” — When matching discrete constants; if-else better for ranges and complex boolean logic.

Next: /java/learn/language/methods/