DEV Community 👩‍💻👨‍💻

DEV Community 👩‍💻👨‍💻 is a community of 966,904 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for Java Switch Case: The Improved Version
Abhinav Pandey
Abhinav Pandey

Posted on

Java Switch Case: The Improved Version

Java 12 introduced switch expressions which improved the way we can write switch-case statements.

Over the next few versions, the switch-case statement has been improved several times. Let's take a look at the improvements and compare them to the original switch-case statement.

1. Arrow Case Expression

Earlier, case blocks were required to end with a break statement. Otherwise, there would be a fall-through problem.

// OLD
switch (x) {
    case 1:
        System.out.println("One");
        break;
    case 2:
        System.out.println("Two");
        break;
    default:
        System.out.println("Unknown");
}
Enter fullscreen mode Exit fullscreen mode

Now, we can use an arrow case expression to simplify the case block. Only the statement appearing after the arrow will be executed if the case matches.

// NEW
switch (x) {
    case 1 -> System.out.println("One");
    case 2 -> System.out.println("Two");
    default -> throw new IllegalArgumentException();
}
Enter fullscreen mode Exit fullscreen mode

This is similar to lambda syntax. If there were multiple statements, we could use a block instead.

// NEW (with block)
switch (x) {
    case 1 -> {
        System.out.println("One");
        System.out.println("One again");
    }
    case 2 -> System.out.println("Two");
    default -> System.out.println("Unknown");
}
Enter fullscreen mode Exit fullscreen mode

2. Multiple matching values

What if a fallthrough was desired? In the old ways, we would have to write a separate case for each value and let it fall through to the last case which will contain the operations.

// OLD (fallthrough)
switch (x) {
    case 1:
    case 2:
        System.out.println("Valid values");
        break;
    default:
        System.out.println("Unknown");
}
Enter fullscreen mode Exit fullscreen mode

In the improved version, this can be done with a comma separated list of values.

// NEW (multiple values)
switch (x) {
    case 1, 2:
        System.out.println("Valid values");
    default:
        System.out.println("Unknown");
}
Enter fullscreen mode Exit fullscreen mode

3. Switch expressions

A big improvement is that switch statements can be used to return a value and therefore can be used as expressiond.

For example, we can use a switch-case block inline to print a value in words.

// switch expressions
System.out.println(switch (x) {
    case 1 -> "One";
    case 2 -> "Two";
    default -> "Unknown";
});
Enter fullscreen mode Exit fullscreen mode

4. The yield keyword

When case has a single statement, as seen above, the value returned by the statement is returned by the switch expression.
If case has a block, we need to explicitly return the value using the yield keyword.

// switch expressions with yield
String word = switch (x) {
    case 1 -> {
        doSomething();
        yield "One";
    }
    case 2 -> "Two";
    default -> "Unknown";
};
Enter fullscreen mode Exit fullscreen mode

Old-style case blocks can also be used in switch expressions and can have a yield statement.
When using a yield statement, a break statement is not required.

This is not recommended though. It's best to stick to the new style in order to avoid confusion and unexpected mistakes.

// old-style case blocks with yield
String word = switch (x) {
    case 1:         
        doSomething();
        yield "One";
    case 2: 
        yield "Two";
    default:
        yield "Unknown";
};
Enter fullscreen mode Exit fullscreen mode

5. Exhaustiveness of switch expressions

Switch case statements are not required to be exhaustive. It is fine if no case matches and there is no default case.
However, when using switch to return a value, it is required that all cases are covered and one of them should always match.

For e.g., when implementing a switch on numbers, the default case cannot be left out:

// missing default case
String word = switch (x) {
    case 1 -> "One";
    case 2 -> "Two";
};

/* gives the error:
error: the switch expression does not cover all possible input values
      String word = switch (x) {
                    ^
*/
Enter fullscreen mode Exit fullscreen mode

This means, we will always need to have a default case unless working with booleans.

The only exception to this is while using an enum and covering all possible enum values.

The below code works fine but it will give the same error as above if we remove one of the cases.

// switch expressions with enum
public class MyClass {
    static enum Color { RED, GREEN, BLUE };

    public static void main(String[] args) {
        Color color = Color.RED;
        System.out.println(switch (color) {
            case RED -> "Red";
            case GREEN -> "Green";
            case BLUE -> "Blue";
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

That's it for the improvements. One more feature worth mentioning is pattern matching but I have not covered it because it is still a preview feature.

An important point to note is that having an improved syntax does not mean the old syntax is invalid now. Both syntaxes work.


Thank you for reading. If you want to connect with me, you can find me on Twitter where I post regular Java tips and quizzes.

Top comments (0)

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.