Control Flow
BeginnerMaster if/else, classic and expression-form switch, all loop variants, break/continue, and the modern switch expressions added in Java 14+.
Overview
Control flow determines the order in which statements execute. Java provides branching (if/else, switch), looping (for, while, do-while, enhanced for-each), and jump statements (break, continue, return). Modern Java has significantly improved switch: Java 14 made switch expressions standard, and Java 21 added pattern matching in switch — enabling safe type dispatch that replaces verbose instanceof chains.
if / else & Conditional Logic
The if statement evaluates a boolean expression. Dangling-else binds to the nearest if. Braces are optional for single statements but always recommended to avoid maintenance bugs.
The ternary operator condition ? a : b is a concise if/else for expressions. Nested ternaries compile but hurt readability — use if/else instead.
Instanceof with pattern matching (Java 16+) combines a type check and cast in one expression.
public class IfElseDemo {
public static String classify(Object obj) {
// Pattern matching instanceof (Java 16+)
if (obj instanceof String s) {
return "String of length " + s.length();
} else if (obj instanceof Integer i && i > 0) {
return "Positive integer: " + i;
} else if (obj == null) {
return "null";
} else {
return "Other: " + obj.getClass().getSimpleName();
}
}
public static void main(String[] args) {
System.out.println(classify("hello")); // String of length 5
System.out.println(classify(42)); // Positive integer: 42
System.out.println(classify(-5)); // Other: Integer
System.out.println(classify(null)); // null
// Ternary
int score = 75;
String result = score >= 60 ? "Pass" : "Fail";
System.out.println(result); // Pass
}
}switch — Classic, Expression & Pattern
Classic switch uses fall-through by default — missing break causes execution to continue into the next case, a common bug.
Switch expressions (Java 14+) eliminate fall-through with the arrow -> syntax, can return values, and the compiler enforces exhaustiveness. Use yield to return a value from a block-form case.
Pattern matching in switch (Java 21) lets you match on types and add guard conditions, replacing long instanceof chains with concise, readable code.
public class SwitchDemo {
// Classic switch (fall-through risk)
static String dayTypeClassic(int day) {
String type;
switch (day) {
case 1: case 7: type = "Weekend"; break;
default: type = "Weekday"; break;
}
return type;
}
// Switch expression (Java 14+) — no fall-through, returns value
static String dayTypeModern(int day) {
return switch (day) {
case 1, 7 -> "Weekend";
default -> "Weekday";
};
}
// Switch expression with yield (block form)
static int discount(String tier) {
return switch (tier) {
case "Gold" -> 20;
case "Silver" -> 10;
default -> {
System.out.println("Unknown tier: " + tier);
yield 0;
}
};
}
// Pattern matching switch (Java 21)
static String describe(Object obj) {
return switch (obj) {
case Integer i when i < 0 -> "Negative int: " + i;
case Integer i -> "Positive int: " + i;
case String s -> "String: " + s;
case null -> "null";
default -> "Other";
};
}
public static void main(String[] args) {
System.out.println(dayTypeModern(1)); // Weekend
System.out.println(discount("Gold")); // 20
System.out.println(describe(-3)); // Negative int: -3
System.out.println(describe("hi")); // String: hi
}
}Loops — for, while, do-while & Enhanced for
Java has four loop constructs:
for loop — classic index-based iteration, best when the count is known upfront. while loop — tests condition before each iteration; body may never execute. do-while loop — tests condition after each iteration; body executes at least once. Enhanced for-each — cleanest syntax for iterating arrays and any Iterable; no index access.
break exits the nearest enclosing loop or switch. continue skips the rest of the current iteration. Labeled break/continue targets an outer loop by name.
public class LoopDemo {
public static void main(String[] args) {
// Standard for loop
for (int i = 0; i < 5; i++) {
System.out.print(i + " "); // 0 1 2 3 4
}
System.out.println();
// While loop
int n = 10;
while (n > 0) {
System.out.print(n + " ");
n -= 3;
}
System.out.println(); // 10 7 4 1
// Do-while — body runs at least once
int x = 0;
do {
System.out.print(x + " ");
x++;
} while (x < 3);
System.out.println(); // 0 1 2
// Enhanced for-each
int[] nums = {1, 2, 3, 4, 5};
int sum = 0;
for (int num : nums) sum += num;
System.out.println("Sum: " + sum); // 15
// Labeled break — exit outer loop from inner loop
outer:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i == 1 && j == 1) break outer;
System.out.print("(" + i + "," + j + ") ");
}
}
// Prints: (0,0) (0,1) (0,2) (1,0)
}
}Key Points to Remember
- Classic switch falls through by default — always add break or migrate to switch expressions
- Switch expressions (Java 14+) with -> eliminate fall-through and can return values
- Pattern matching in switch (Java 21) replaces instanceof chains with guard-aware type matching
- do-while guarantees at least one execution; while may execute zero times
- Enhanced for-each is cleaner but gives no index; use classic for when you need the index
- Labeled break outer exits a named outer loop — useful in matrix traversal problems
Practice Control Flow in the Playground
Run and modify code directly in your browser - no setup needed.
Interview Questions
Sign in to ask AriaWhat is fall-through in a switch statement and how do you prevent it?
What is the difference between break and continue?
When would you use a do-while loop instead of a while loop?
How does switch expression differ from switch statement in Java 14+?
How does pattern matching in switch (Java 21) work? Give an example.
Ask Aria about Control Flow
Your personal AI tutor — ask anything about this concept