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();
}
// *
// ***
// *****
// *******
// *********
}
}