Java Switch Expressions

Like all expressions, java switch expressions evaluate to a single value and can be used in statements. They may contain “case L ->” labels that eliminate the need for break statements to prevent fall through. You can use a yield statement to specify the value of a switch expression.

Extend switch so it can be used as either a statement or an expression, and so that both forms can use either traditional case ... : labels (with fall through) or new case ... -> labels (with no fall through), with a further new statement for yielding a value from a switch expression. These changes will simplify everyday coding, and prepare the way for the use of pattern matching in switch. This was a preview language feature in JDK 12 and JDK 13.

 

Java Switch Expressions

History​

Switch expressions were proposed in December 2017 by JEP 325. JEP 325 was targeted to JDK 12 in August 2018 as a preview feature. One aspect of JEP 325 was the overloading of the break statement to return a result value from a switch expression. Feedback on JDK 12 suggested that this use of break was confusing. In response to the feedback, JEP 354 was created as an evolution of JEP 325. 

JEP 354 proposed a new statement, yield, and restored the original meaning of break. JEP 354 was targeted to JDK 13 in June 2019 as a java preview feature. Feedback on JDK 13 suggested that switch expressions were ready to become final and permanent in JDK 14 with no further changes.

"case L ->" Labels

Consider the following switch statement in java that prints the number of letters of a day of the week:

				
					public enum Day { SUNDAY, MONDAY, TUESDAY,
    WEDNESDAY, THURSDAY, FRIDAY, SATURDAY; }

// ...

    int numLetters = 0;
    Day day = Day.WEDNESDAY;
    switch (day) {
        case MONDAY:
        case FRIDAY:
        case SUNDAY:
            numLetters = 6;
            break;
        case TUESDAY:
            numLetters = 7;
            break;
        case THURSDAY:
        case SATURDAY:
            numLetters = 8;
            break;
        case WEDNESDAY:
            numLetters = 9;
            break;
        default:
            throw new IllegalStateException("Invalid day: " + day);
    }
    System.out.println(numLetters);
				
			

It would be better if you could “return” the length of the day’s name instead of storing it in the variable numLetters; you can do this with a switch expression in java. Furthermore, it would be better if you didn’t need break statements to prevent fall through; they are laborious to write and easy to forget. You can do this with a new kind of case label. The following is a switch expression that uses the new kind of case label to print the number of letters of a day of the week:

				
					    Day day = Day.WEDNESDAY;    
    System.out.println(
        switch (day) {
            case MONDAY, FRIDAY, SUNDAY -> 6;
            case TUESDAY                -> 7;
            case THURSDAY, SATURDAY     -> 8;
            case WEDNESDAY              -> 9;
            default -> throw new IllegalStateException("Invalid day: " + day);
        }
    );    
				
			

The new kind of case label has the following form:

case label_1, label_2, ..., label_n -> expression;|throw-statement;|block
 

When the Java runtime matches any of the labels to the left of the arrow, it runs the code to the right of the arrow and does not fall through; it does not run any other code in the switch expression (or statement). If the code to the right of the arrow is an expression, then the value of that expression is the value of the switch expression.

You can use the new kind of case label in switch statements. The following is like the first example, except it uses “case L ->” labels instead of “case L:” labels:

				
					    int numLetters = 0;
    Day day = Day.WEDNESDAY;
    switch (day) {
        case MONDAY, FRIDAY, SUNDAY -> numLetters = 6;
        case TUESDAY                -> numLetters = 7;
        case THURSDAY, SATURDAY     -> numLetters = 8;
        case WEDNESDAY              -> numLetters = 9;
        default -> throw new IllegalStateException("Invalid day: " + day);
    };
    System.out.println(numLetters);
				
			

A “case L ->” label along with its code to its right is called a switch labeled rule in java.

"case L:" Statements and the yield Statement

You can use “case L:” labels in switch expressions; a “case L:” label along with its code to the right is called a switch labeled statement group:

Day day = Day.WEDNESDAY;

int numLetters = switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
System.out.println(6);
yield 6;
case TUESDAY:
System.out.println(7);
yield 7;
case THURSDAY:
case SATURDAY:
System.out.println(8);
yield 8;
case WEDNESDAY:
System.out.println(9);
yield 9;
default:
throw new IllegalStateException("Invalid day: " + day);
};
System.out.println(numLetters);
 
 

The previous example uses java yield statements. They take one argument, which is the value that the case label produces in a switch expression.

The yield statement makes it easier for you to differentiate between switch statements and switch expressions. A switch statement, but not a switch expression, can be the target of a break statement. Conversely, a switch expression, but not a switch statement, can be the target of a yield statement.

Note:

It’s recommended that you use “case L ->” labels. It’s easy to forget to insert break or yield statements when using “case L:” labels; if you do, you might introduce unintentional fall through in your code.

For “case L ->” labels, to specify multiple statements or code that are not expressions or throw statements, enclose them in a block. Specify the value that the case label produces with the yield statement:

int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> {
System.out.println(6);
yield 6;
}
case TUESDAY -> {
System.out.println(7);
yield 7;
}
case THURSDAY, SATURDAY -> {
System.out.println(8);
yield 8;
}
case WEDNESDAY -> {
System.out.println(9);
yield 9;
}
default -> {
throw new IllegalStateException("Invalid day: " + day);
}
};
 
 

Exhaustiveness

Unlike switch statements, the cases of java switch expressions must be exhaustive, which means that for all possible values, there must be a matching switch label. Thus, switch expressions normally require a default clause. However, for enum switch expressions that cover all known constants, the compiler inserts an implicit default clause.

In addition, a switch expression must either complete normally with a value or complete abruptly by throwing an exception. For example, the following code doesn’t compile because the switch labeled rule doesn’t contain a yield statement:

int i = switch (day) {
case MONDAY -> {
System.out.println("Monday");
// ERROR! Block doesn't contain a yield statement
}
default -> 1;
};
 
 

The following example doesn’t compile because the switch labeled statement group doesn’t contain a yield statement in java:

i = switch (day) {
case MONDAY, TUESDAY, WEDNESDAY:
yield 0;
default:
System.out.println("Second half of the week");
// ERROR! Group doesn't contain a yield statement
};
 
 

Because a java switch expression must evaluate to a single value (or throw an exception), you can’t jump through a switch expression with a breakyieldreturn, or continue statement, like in the following example:

z:
for (int i = 0; i < MAX_VALUE; ++i) {
int k = switch (e) {
case 0:
yield 1;
case 1:
yield 2;
default:
continue z;
// ERROR! Illegal jump through a switch expression
};
// ...
}

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top