created on | January 9, 2024 |
The traditional switch statement has a test expression and a switch code block. In a switch code block, only switch statements are allowed. A switch statement starts with a label and a value or a label, followed by a colon, followed by one or more statements;
The switch statement evaluates its test expression, then executes all statements that follow the matching case label until it hits a statement.
In the traditional switch statement, for the test expression, byte, short, char, int primitive data types, Enum types and String are allowed (String since Java 7).
In labels, only literals and constants are allowed.
Consider a method that checks the value of an int and returns true for values of 0, 1 and -1 and false otherwise.
Because there is no statement after the and label, for values of 0 or 1 the statement with label is executed. In this case and are fall through labels.
An alternative, shorter form for switch block for the method above is
Here, no statement is necessary, because we bail out of the switch block with . But multiple return statements tend to make some devs nervous, especially in more complex switch statements.
There are a few notable things in the new extended form of the traditional switch statement:
The code to the right of a “case L ->” switch label is restricted to be an expression, a block, or (for convenience) a throw statement.
You can mix the traditional and extended form. That is, you can use the labels and . In this case values are yielded using the break with value statement:
The cases of a switch expression must be exhaustive. For any possible value there must be a matching switch label, which means that more often than not a default clause is required.
A switch expression must complete with a value, or throw an exception. The compiler checks that for every switch label, if it is matched then a value can be yielded (or an exception is thrown).
For multiple statements in a switch branch, code blocks with curly braces must be used. The return value of the corresponding branch must be returned with :
In the switch statement above,
is implicitly translated to
Note that you can use only inside a code block. The following statement would result in a compiler error Cannot resolve symbol ‘yield’.
Traditionally, switch statements and expressions throw NullPointerException if the selector expression evaluates to null, so testing for null must be done outside the switch:
This has been relaxed by introducing a new null label for a case, that matches when the value of the selector expression is null. The code above can thus be written in a more concise form:
With two types and :
we can write a switch statment like:
The switch is exhausting, because the class is sealed and permits only the subclasses and . If the class wouldn’t be sealed, a label would be necessary.
In the example above, in the statement for the pattern , the pattern variable is not used. The compiler reports the warning Pattern variable ‘a’ is not used. Unused pattern variables can be set to be ignored with the keyword :
in the following switch statement:
With the code above, the compiler reports the error [line:column] java: this case label is dominated by a preceding case label.
The first pattern labele dominates the second pattern label because every value that matches the pattern also matches the pattern , but not vice versa, because String is a subtype of CharSequence.
A type pattern p of type U is total for a type T, if T is a subtype of U. For example, the type pattern CharSequence and Object are total for the type String. In the code above, CharSequence cs is a total type pattern.
The two match-all labels are and total type patterns.
It is also a compile-time error if a switch block has more than one match-all switch label.
A new kind of pattern called guarded pattern, written p when b, that allows a pattern p to be refined by an arbitrary boolean expression b, i.e.:
The Java™ Tutorials, The switch Statement