Java Switch Statement

Java switch statements help in providing multiple possible execution paths for a program. Java switch statements can be used in place of if-else statements to write more cleaner and concise code.

Java switch statements have evolved over time. In this tutorial, we will learn about basic switch statement features and new features in later versions of Java.

1. Switch Statements

1.1. Syntax

The general form of a switch statement is –

switch (expression)
{
        case labelOne:
                statements;
 		break;

        case labelTwo:
                statements;
 		break;

        case labelThree:
                statements;
 		break;

        default:
                statements;
}

The expression value must be one of the following 6 types:

Here labelOne, labelTwo and labelThree are “compile-time constant expressions” or constants (the value of the labels must be known at compile-time).

We can achieve similar functionality with a chain of if-else blocks, but the switch statement is more readable and clean.

1.2. Execution Flow

A switch statement is evaluated as follows:

  1. First of all, the switch expression is evaluated.
  2. The datatype of the expression value and case labels must be same.
  3. Second, the value of expression is matched against the value of each case label. If the value of the expression matches a case label, the execution starts from the matched case label and executes all statements until the break statement is encountered.
  4. If the value of the expression does not match any case label, execution starts at the statement following the optional default label and continues until the end of the switch statement or the break statement is encountered.

We can easily guess that the use of a break statement inside the default label is not necessary because the default label is the last label in the switch statement and the execution of the switch statement will stop after that anyway.

1.3. Demo

In this example, we are checking if today is a weekend or weekday, using the switch statement. For storing all the days in a week, we have created an enum.

Notice how we have created a total of eight case labels that return an appropriate true or false value.

public class SwitchStatement 
{
    public static void main(String[] args) 
    {
        System.out.println("Monday is : " + isWeekDay(Day.TUE));
        System.out.println("Monday is : " + isWeekDay(Day.SUN));
    }
    
    public static Boolean isWeekDay(Day day) 
    {
        Boolean result = false;
        switch(day) {
            case MON: 
                result = true;
                break;
            case TUE: 
                result = true;
                break;
            case WED: 
                result = true;
                break;
            case THUR: 
                result = true;
                break;
            case FRI: 
                result = true;
                break;
            case SAT: 
                result = false;
                break;
            case SUN: 
                result = false;
                break;
            default: 
                throw new IllegalArgumentException("Invalid day: " + day.name())
        }
        return result;
    }
}

enum Day {
    MON, TUE, WED, THUR, FRI, SAT, SUN
}

The above example works as expected, but we can make it better. As we see that multiple case labels are returning the same value, so we can group the case labels to make the code more readable.

public static Boolean isWeekDay(Day day) 
{
    Boolean result = false;
    switch(day) {
        case MON, TUE, WED, THUR, FRI: 
            result = true;
            break;
        case SAT, SUN: 
            result = false;
            break;
        default: 
            throw new IllegalArgumentException("Invalid day: " + day.name())
    }
    return result;
}

There is still a chance of improvement. In the above example, having the break statements does not look good. We can remove the break statements using the new arrow syntax. It is available since Java 13.

public static Boolean isWeekDay(Day day) 
{
    Boolean result = false;
    switch(day) {
        case MON, TUE, WED, THUR, FRI -> result = true;
        case SAT, SUN -> result = false;
        default -> throw new IllegalArgumentException("Invalid day: " + day.name());
    }
    return result;
}

2. Switch Expressions

Java 12 introduced the switch expressions which can compute the value for the whole switch statement and assign its value to a variable. It is very similar to other normal Java statements.

2.1. Return value with Arrow Syntax

Let us rewrite the last example, with a switch expression. Notice line no. 11 where we are directly assigning the value of the switch statement to the variable result.

public class SwitchStatement 
{
    public static void main(String[] args) 
    {
        System.out.println("Monday is : " + isWeekDay(Day.TUE));
        System.out.println("Monday is : " + isWeekDay(Day.SUN));
    }
    
    public static Boolean isWeekDay(Day day) 
    {
         Boolean result = switch(day) {
            case MON, TUE, WED, THUR, FRI ->  true;
            case SAT, SUN -> false;
            default -> throw new IllegalArgumentException("Invalid day: " + day.name());
        };
        return result;
    }
}

enum Day {
    MON, TUE, WED, THUR, FRI, SAT, SUN
}

2.2. Return Value with yield Keyword

In the above example, we are writing only the return value in the case statements. What if we have to execute multiple statements before returning any value from a given case block.

In such cases, yield keyword helps in returning a computed value from a multi-statement block.

In the given example, we have written only a print statement. You can write as many statements as needed.

public static Boolean isWeekDay(Day day) 
{
     Boolean result = switch(day) {
        case MON, TUE, WED, THUR, FRI ->  {
            System.out.println("It's Weekday");
            yield true;
        }
        case SAT, SUN -> {
            System.out.println("It's Weekend");
            yield false;
        }
        default -> throw new IllegalArgumentException("Invalid day: " + day.name());
    };
    return result;
}

3. Switch Examples

3.1. Better instanceof checking with Switch Statements

Traditionally, if we had to write a code that checks the instance type and perform some logic, it was the way:

Object o;
if (o instanceof String) 
{
    String s = (String) o;
    String.format("String %s", s)
} 
else if (o instanceof Integer) 
{
    Integer i = (Integer) o; 
    String.format("int %d", i)
} 
else if (o instanceof Double) 
{
    Double d = (Double) o;
    String.format("double %f", d)
}

In Java 17, we can rewrite the whole expression in the following manner;

Object o;
switch (o) 
{
    case Integer i -> String.format("int %d", i);
    case Double d  -> String.format("double %f", d);
    case String s  -> String.format("String %s", s);
    default        -> o.toString();
}

3.2. Handling null Values

Traditional switch statements throw NullPointerException if the selector expression evaluates to null.

From Java 17, we can check for null values as the separate case itself.

if (s == null) {
    System.out.println("oops!");
    return;
}
switch (s) {
    case "Foo", "Bar" -> System.out.println("Great");
    default           -> System.out.println("Ok");
}
switch (s) {
    case null         -> System.out.println("Oops");
    case "Foo", "Bar" -> System.out.println("Great");
    default           -> System.out.println("Ok");
}

4. Restrictions

4.1. Case Label Values Must be in Range of DataType

Please note that the value of the constant expressions used as the case labels must be in the range of the data type of switch expression.

The range of the byte data type in Java is -128 to 127, so the following code would not compile because the second case label is 150, which is outside the range of the byte data type:

byte b = 10;
switch (b) {
        case 5:
                b++;
                break;

        case 150:       // A compile-time error. 150 is greater than 127
                b--;
                break;

        default:
                b = 0;
}

4.2. Duplicate Case Labels are Not Allowed

Another important point to note is that two case labels in a switch statement cannot be the same. The following piece of code would not compile because case label 10 is repeated:

int num = 10;
switch (num) {
        case 10:
                num++;
                break;

        case 10: // A compile-time error. Duplicate case label 10
                num--;
                break;

        default:
                num = 100;
}

Happy Learning !!

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode