Control Flow · Lesson 10 of 42
if-else and switch
Programs become useful when they make decisions: approve the loan or reject it, show the dashboard or the login page. Java offers if/else for general conditions and switch for choosing between many fixed values – and modern Java has turned switch into a far more powerful tool than the one in older textbooks.
In this lesson
if,else if,elseand nested conditions- The classic
switchand its fall-through trap - Arrow-style switch expressions (Java 14+) and
yield - Pattern matching in switch (Java 21)
if, else if, else
public class Main {
public static void main(String[] args) {
int marks = 82;
String grade;
if (marks >= 90) {
grade = "A+";
} else if (marks >= 75) {
grade = "A";
} else if (marks >= 60) {
grade = "B";
} else if (marks >= 40) {
grade = "C";
} else {
grade = "Fail";
}
System.out.println("Marks " + marks + " → " + grade);
}
}
Marks 82 → A
The chain stops at the first true condition
- marks >= 90?82 – no
- marks >= 75?yes → grade = "A"
- Skip the restremaining else-if and else are ignored
The condition must be a boolean. Unlike C, Java does not treat numbers as true/false – if (count) is a compile error; write if (count != 0).
Common mistake: if without braces
Without braces only the next statement belongs to the if. Adding a second indented line later doesn't make it conditional – a classic source of bugs. Always use braces, even for one line.
Guard clauses keep code flat
public class Main {
static String withdraw(double balance, double amount) {
if (amount <= 0) return "Invalid amount";
if (amount > balance) return "Insufficient balance";
if (amount > 25000) return "Daily limit exceeded";
return "Dispensed ₹" + amount;
}
public static void main(String[] args) {
System.out.println(withdraw(5000, 2000));
System.out.println(withdraw(5000, 9000));
System.out.println(withdraw(50000, 30000));
}
}
Dispensed ₹2000.0 Insufficient balance Daily limit exceeded
The classic switch
switch compares one value against many case labels. It works with int, char, String, enums and (since Java 21) any object type with patterns.
public class Main {
public static void main(String[] args) {
int day = 3;
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
default:
System.out.println("Another day");
}
}
}
Wednesday
The fall-through trap
In the classic form, execution continues into the next case unless you break:
public class Main {
public static void main(String[] args) {
String role = "editor";
switch (role) {
case "admin":
System.out.println("can delete");
case "editor":
System.out.println("can edit");
case "viewer":
System.out.println("can view");
break;
default:
System.out.println("no access");
}
}
}
can edit can view
Here fall-through is deliberate (each role has the permissions of the roles below it), but forgetting a break by accident is one of the most common Java bugs – and one of the most common output questions.
Switch expressions (modern Java)
Since Java 14, switch can use arrows. Arrow cases never fall through, several labels can share a case, and the whole switch can return a value:
public class Main {
public static void main(String[] args) {
int day = 6;
String type = switch (day) {
case 1, 2, 3, 4, 5 -> "Weekday";
case 6, 7 -> "Weekend";
default -> throw new IllegalArgumentException("Bad day: " + day);
};
System.out.println(type);
String plan = "pro";
int price = switch (plan) {
case "free" -> 0;
case "pro" -> {
int base = 499;
int gst = base * 18 / 100;
yield base + gst; // yield returns a value from a block
}
default -> -1;
};
System.out.println("Pro costs ₹" + price);
}
}
Weekend Pro costs ₹588
Why prefer switch expressions?
No accidental fall-through, less code, and the compiler checks that every possible value is handled when you switch over an enum or a sealed type – forgetting a case becomes a compile error instead of a bug in production.
Pattern matching in switch (Java 21)
Java 21 lets switch test the type of an object and bind it to a variable, with optional when guards:
public class Main {
static String describe(Object o) {
return switch (o) {
case null -> "nothing";
case Integer i when i < 0 -> "negative number " + i;
case Integer i -> "number " + i;
case String s when s.isBlank() -> "empty text";
case String s -> "text of length " + s.length();
case int[] arr -> "array of " + arr.length + " ints";
default -> "something else: " + o.getClass().getSimpleName();
};
}
public static void main(String[] args) {
System.out.println(describe(42));
System.out.println(describe(-7));
System.out.println(describe("Java"));
System.out.println(describe(new int[]{1, 2, 3}));
System.out.println(describe(3.5));
System.out.println(describe(null));
}
}
number 42 negative number -7 text of length 4 array of 3 ints something else: Double nothing
The same idea works with instanceof: if (o instanceof String s && s.length() > 3) checks the type and gives you a typed variable s in one step – no manual cast.
if-else or switch?
| Situation | Use |
|---|---|
Ranges and complex conditions (marks >= 75 && attendance > 80) | if/else if |
| One value against many constants (menu option, status, enum) | switch expression |
| Different behaviour per object type | pattern-matching switch |
Practice
Try it yourself
Write a switch expression that returns the number of days in a month (ignore leap years).
Show solution
public class Main { public static void main(String[] args) { int month = 4; int days = switch (month) { case 2 -> 28; case 4, 6, 9, 11 -> 30; default -> 31; }; System.out.println(days); } }30
Classify a character as vowel, consonant, digit or other.
Show solution
public class Main { public static void main(String[] args) { char ch = 'E'; String kind; if (Character.isDigit(ch)) { kind = "digit"; } else if (Character.isLetter(ch)) { kind = "aeiou".indexOf(Character.toLowerCase(ch)) >= 0 ? "vowel" : "consonant"; } else { kind = "other"; } System.out.println(ch + " is a " + kind); } }E is a vowel
Quick check
What happens if you forget break in a classic switch case?
Execution falls through into the following case(s) until a break or the end of the switch.
Can arrow-style cases fall through?
No. Each arrow case runs only its own code.
What does yield do?
It returns a value from a block inside a switch expression.
Summary
ifconditions must be booleans; always use braces; guard clauses keep code flat.- Classic switch falls through without
break; arrow switch expressions don't and can return values. - Java 21 pattern matching lets switch branch on types with
whenguards.
Finished this lesson?
Mark it complete to track your progress, then carry on with the next lesson.