Contents

If and Switch Statements in Java

Written by: David Vlijmincx

Introduction

Conditional statements are used to control the flow in your application. In this post, we'll look at if/else statements, switch statements, and the newer pattern matching for switch expressions.

If and Else Statements

The if statement is the most basic form of conditional execution. It allows you to execute different code blocks based on a true or false condition.

Basic If Statement

The most basic version is just a single if statement. The code between the {} is only executed if the condition is true. In the next example that would be when the temperature is higher than 30.

1
2
3
4
int temperature = 40;
if (temperature > 30) {
    System.out.println("It's hot outside!");
}

You can also add an else{} that would be executed when the if statement is not true.

Using Logical AND (&&)

The AND operator requires both conditions to be true for the code block to execute. This is useful when you need to check multiple conditions at the same time.

1
2
3
4
5
6
7
boolean hasTicket = true;
int age = 15;
if (hasTicket && age >= 18) {
    System.out.println("You can enter the movie");
} else {
    System.out.println("You cannot enter the movie");
}

Using Logical OR (||)

The OR operator executes the code between the {} if at least one of the condition is true. This is useful when you execute code when one of the two conditions makes it oke to run the code.

1
2
3
4
5
6
7
boolean isHoliday = true;
boolean isWeekend = false;
if (isHoliday || isWeekend) {
    System.out.println("No work today!");
} else {
    System.out.println("Time to work");
}

In this case the if statement will run because isHoliday is true.

Combining AND and OR Operators

For more complex logic, you can combine AND and OR operators. You can also use parentheses to control the order of evaluation. In the following example both operators are used:

1
2
3
4
5
6
7
boolean hasMembership = true;
int purchaseAmount = 150;
if ((hasMembership && purchaseAmount > 100) || purchaseAmount > 200) {
    System.out.println("You get a discount!");
} else {
    System.out.println("No discount available");
}

In this example first the condition between the parentheses is evaluated. The result is than used for the surrounding statement. In this case the condition is true.

Else-If

When you need to check multiple conditions in one after each other, use an else-if. The conditions are checked in order until one is true, or the else statement is executed. In the following example the time is greater than 12 but still less than twelve making the first if statement false.

1
2
3
4
5
6
7
8
int time = 14;
if (time < 12) {
    System.out.println("Good morning!");
} else if (time < 18) {
    System.out.println("Good afternoon!");
} else {
    System.out.println("Good evening!");
}

In this example the second if statement is true.

Nested If Statements with Multiple Conditions

For complex decision, you can nest if statements and combine them with logical operators. In the following example you can see an If statement inside another if statement.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
boolean isWeekend = true;
boolean isRaining = false;
boolean hasUmbrella = true;

if (isWeekend) {
    if (!isRaining || (isRaining && hasUmbrella)) {
        System.out.println("Let's go to the park!");
    } else {
        System.out.println("Let's stay home.");
    }
}

When doing things like this it is important to keep readability in mind. It can be quite hard to debug when multiple if statements are nested.

Switch Statements

Switch statements provide a way to handle multiple conditions, especially when comparing a single variable against several possible cases.

Basic Switch Statement

The traditional switch statement is ideal for comparing a single value against multiple constants. Note that each case requires a break statement. If the break wasn't there the next case would also be evaluated.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
String day = "MONDAY";
switch (day) {
    case "MONDAY":
        System.out.println("Start of work week");
        break;
    case "FRIDAY":
        System.out.println("End of work week");
        break;
    default:
        System.out.println("Midweek");
        break;
}

In the previous example you can see how a String is compared against multiple cases. When no match is found the default will be executed.

Switch with Fall-Through Cases

Sometimes you want multiple cases to execute the same code. You can do this by not using the break statement between cases.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
String day = "SATURDAY";
switch (day) {
    case "SATURDAY":
    case "SUNDAY":
        System.out.println("Weekend!");
        break;
    case "MONDAY":
    case "TUESDAY":
    case "WEDNESDAY":
    case "THURSDAY":
    case "FRIDAY":
        System.out.println("Weekday");
        break;
    default:
        System.out.println("Invalid day");
        break;
}

In the previous example monday to friday all have the same behaviour.

Switch Expression with Arrow Syntax

Java 12 introduced switch expressions with arrow syntax, allowing more concise code and automatic returns.

1
2
3
4
5
6
7
int dayNumber = 3;
String dayType = switch (dayNumber) {
    case 1, 2, 3, 4, 5 -> "Weekday";
    case 6, 7 -> "Weekend";
    default -> "Invalid day";
};
System.out.println("Day type: " + dayType);

This code is more concise than the previous examples. This makes reading it easier, and you can't forget the return/ break statement.

Pattern Matching for Switch Expressions

Pattern matching for switch expressions was added in Java 21. This makes writing switch statements a lot more fluent and easier to read as well.

Basic Type Pattern Matching

You can use pattern matching to match the type of an object and handle each case differently.

1
2
3
4
5
6
7
8
9
Object obj = "Hello";
String result = switch (obj) {
    case String s -> "String of length: " + s.length();
    case Integer i -> "Integer value: " + i;
    case Long l -> "Long value: " + l;
    case null -> "Null value";
    default -> "Unknown type";
};
System.out.println(result);

In the previous example an Object is matched against different cases and based on that type some code is executed. Notice that you don't have to do any casting inside those cases.

Pattern Matching with Guards

Guard patterns allow you to add additional conditions to your case statements, making them more specific.

1
2
3
4
5
6
7
8
9
Number number = 42;
String description = switch (number) {
    case Integer i when i < 0 -> "Negative integer";
    case Integer i when i > 0 -> "Positive integer";
    case Integer i -> "Zero";
    case Double d -> "Double value";
    default -> "Other number type";
};
System.out.println(description);

This is handy when the type is the same, but you want to do something based on a type but also need to take the value of that object into account.

Pattern Matching classes

Pattern matching also works with classes. If you want to check a value of a class or record that also works. In the following example the values of the record are used to make the cases more specific.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
record Point(int x, int y) {}

public static void main(String[] args) {
    Object obj = new Point(1, 2);
    String description = switch (obj) {
        case Point p when p.x() == 0 && p.y() == 0 -> "Origin point";
        case Point p when p.x() == p.y() -> "Point on diagonal";
        case Point p -> String.format("Point at (%d, %d)", p.x(), p.y());
        default -> "Not a point";
    };
    System.out.println(description);
}

This would also work with Classes.

Conclusion

In this post, we looked at different ways of controlling the flow of your application. Depending on the situation, number of cases, and readability you can use any of these options to control the flow.