A conditional is a structure that chooses which code to execute based on a condition.
Until now, our programs started on the first line and executed all instructions to the end without deviating.
But real software needs to make decisions. We need the code to react differently depending on whether the user is of legal age or not, whether a password is correct, or whether today is the weekend.
Today we are going to look at conditional control structures. And get ready, because if you learned Java years ago, you’re in for a treat with the new Switch.
The if and else statement
This is the fundamental structure of programming. “If this happens, do that.”
The syntax in Java is identical to C, C++, or C#. We need a condition that evaluates to a boolean (true or false).
int battery = 15;
if (battery < 20) {
System.out.println("Low battery! Connect the charger.");
} else {
System.out.println("Battery sufficient.");
}Nesting and else if
We can chain as many conditions as we want. Java will evaluate them in order and execute only the first block whose condition is true.
int grade = 8;
if (grade >= 9) {
System.out.println("Outstanding");
} else if (grade >= 7) {
System.out.println("Notable");
} else if (grade >= 5) {
System.out.println("Pass");
} else {
System.out.println("Fail");
}Braces are your friends
In Java, if the if block only has one line, the braces {} are optional.
Veteran tip: ALWAYS USE THEM. Omitting them is the cause of famous bugs (like the Apple’s goto fail).
The classic switch (statement)
When we need to check a single variable against many different values, using if-else-if-else becomes messy and slow to read.
That’s what switch is for.
Historically, switch in Java (and in C++) has had a bad reputation for being verbose and error-prone. Let’s see how the “classic” form (which still works) looked:
int dayOfWeek = 3;
String dayName;
switch (dayOfWeek) {
case 1:
dayName = "Monday";
break;
case 2:
dayName = "Tuesday";
break;
case 3:
dayName = "Wednesday";
break;
default:
dayName = "Invalid day";
break;
}The problem of “fall-through”
Notice the break statements. If you forget to put one, Java will continue executing the code of the next case. This is called fall-through. Sometimes it is useful, but 99% of the time it’s a bug that will be costly to find.
The modern switch expression (Java 14+)
Java 14 brought one of the most anticipated syntax improvements: Switch Expressions.
This changes two fundamental things:
- Arrow syntax (
->): Cleaner and without the need forbreak. It prevents accidental fall-through. - It’s an Expression: This means the
switchreturns a value. We can assign it directly to a variable.
See the difference with the previous example:
int dayOfWeek = 3;
// Assign the result of the switch directly to the variable
String dayName = switch (dayOfWeek) {
case 1 -> "Monday";
case 2 -> "Tuesday";
case 3 -> "Wednesday";
case 4, 5 -> "Thursday or Friday"; // We can group cases
default -> "Invalid day";
}; // Note the semicolon, it's an assignment!Much more elegant, right?
The yield keyword
Sometimes, within a case of the new switch, you need to do more things before returning the value (calculate something, log something, etc.). In that case, we use braces {} and the yield keyword to return the value.
String dayType = switch (dayOfWeek) {
case 1, 2, 3, 4, 5 -> {
System.out.println("Time to work...");
yield "Workday"; // Returns "Workday"
}
case 6, 7 -> "Weekend";
default -> throw new IllegalArgumentException("Impossible day: " + dayOfWeek);
};Exhaustiveness:
When you use switch as an expression (to return a value), you must cover all possible cases. If you use an int, you need a default. If you use an Enum and cover all options, the default is not necessary (another huge advantage of Enums).