Java Arena
Step 2 of 5

switch expressions and arrows

Since Java 14, a case can be written with an arrow, ->, in place of the colon. An arrow case runs only what's after its arrow, and never falls through, so it needs no break:

int button = 2;
switch (button) {
    case 1 -> System.out.println("Chips");
    case 2 -> System.out.println("Chocolate bar");
    case 4, 5 -> System.out.println("Water");
    default -> System.out.println("No such button");
}
Output
Chocolate bar

After an arrow comes one statement, or a block in braces for several. Several values share a case with commas, case 4, 5 ->. One switch uses either colons or arrows, not both.

A switch that gives a value

Most switches choose a value: the name of a snack, a price, a number of points. Since Java 14, a switch can be an expression, which gives a value like a + b does. The value of each case is what comes after its arrow:

int button = 4;
String snack = switch (button) {
    case 1 -> "Chips";
    case 2 -> "Chocolate bar";
    case 3 -> "Apple";
    case 4, 5 -> "Water";
    default -> "nothing";
};
System.out.println("You get: " + snack);
Output
You get: Water
  • The whole switch (...) { ... } is the value given to snack, so the statement ends with a semicolon after the closing brace.
  • Every case gives a value of the same kind, here a String.
  • A switch expression can be used wherever a value can: assigned to a variable, printed, or returned, as in return switch (button) { ... };.

Every value needs a case

A variable must get a value, so a switch expression must have a case for every value its selector can have. For an int, that means a default:

public class Main {
    public static void main(String[] args) {
        int button = 4;
        String snack = switch (button) {
            case 1 -> "Chips";
            case 2 -> "Chocolate bar";
        };
        System.out.println(snack);
    }
}
What javac prints
Main.java:4: error: the switch expression does not cover all possible input values
        String snack = switch (button) {
                       ^
1 error

A switch statement with arrows, like the first example of this step, has no such rule: a value without a case simply does nothing.

Several statements: yield

When a case needs a few statements to work out its value, the arrow is followed by a block, and yield gives the block's value. Buttons 6 to 9 are sandwiches, which cost more on the weekend:

public class Main {
    public static void main(String[] args) {
        System.out.println(price(2, false));
        System.out.println(price(7, false));
        System.out.println(price(7, true));
    }

    public static int price(int button, boolean weekend) {
        return switch (button) {
            case 1, 2, 3 -> 150;
            case 4, 5 -> 120;
            case 6, 7, 8, 9 -> {
                int base = 350;
                if (weekend) {
                    base = base + 50;
                }
                yield base;
            }
            default -> 0;
        };
    }
}
Output
150
350
400

yield base; ends the block, and base becomes the value of the switch. It's yield, not return: a return would try to leave the whole method, and javac doesn't allow it inside a switch expression. A block that reaches its end without a yield doesn't compile either: javac says "switch rule completes without providing a value".

Your task

Challenge 1 of 3

A shopping mall's directory sign shows what is on each level. The program reads a floor's number, a whole number on one line, and prints its place, with a chain of if and else if. Rewrite it so that a switch expression with arrows gives the place, and the program prints it. Keep what it prints the same: Parking for -1, Lobby for 0, Shops for 1, Food court for 2, and Offices for any other floor. With the input 2, the program prints:

Food court

Challenge 2

A calendar needs the number of days in each month of a year that isn't a leap year. Write the method daysInMonth(int month), which returns the number of days in the month (1 is January, 12 is December) with a switch expression with arrows: 31 for months 1, 3, 5, 7, 8, 10 and 12, 30 for months 4, 6, 9 and 11, and 28 for month 2. For any other number it returns 0. Give each number of days one case, with several values per case. The check runs System.out.println(daysInMonth(4));, which prints:

30

Challenge 3

A parcel service charges by zone, in cents. Write the method postage(int zone, int grams) with a switch expression on the zone:

  • zone 1 (the same town): 150, whatever the weight
  • zone 2 (the same country): 300, whatever the weight
  • zone 3 (abroad): 800, plus 50 for each full 100 grams over 500 grams. A parcel of 1250 grams is 750 grams over, which holds seven full hundreds, so it costs 800 + 7 * 50 = 1150.
  • any other zone: -1

Work out zone 3's price in a block that ends with yield. The check runs System.out.println(postage(3, 1250));, which prints:

1150