The switch Expression with the Arrow (->) Notation – Control Flow

The switch Expression with the Arrow (->) Notation

The switch expression with the arrow notation also has the same form as the switch statement with the arrow notation (Figure 4.4), except that the execution of the switch body must result in a value (or it must throw an exception).

The execution of the switch rules in a switch expression is mutually exclusive, analogous to the switch rules in a switch statement (Figure 4.5). Once the action in the switch rule has completed execution, the value computed by the action is returned and the execution of the switch expression terminates. There is no fall-through and no break statement is allowed.

Whereas the actions in the switch rules of a switch statement only allowed an expression statement (Figure 4.5), the actions in the switch rules of a switch expression allow any expression, in addition to allowing a block or throwing an exception, as in the switch rules of a switch statement.

By far, the canonical action of a case label in a switch rule of a switch expression is an arbitrary expression. Such an expression is always terminated by a semicolon (;). The expression value is returned as the value of the switch expression whose execution is then terminated. Note that no yield statement is necessary or allowed.

Click here to view code image


case 1 -> “ONE”;
case 2 -> yield “two”;       // Compile-time error!

A block of statements can be used if program logic should be refined, but the last statement in the block should be a yield statement to return its value and terminate the execution of the switch expression (alternatively, the last statement can be a throw statement). In a switch expression with the arrow notation, the yield statement is only allowed as the last statement in a block that constitutes the action in a switch rule.

Click here to view code image


case ALARM     -> { soundTheAlarm();
                    callTheFireDepartment();
                    yield Status.EVACUATE; }  // OK
case ALL_CLEAR -> { yield Status.NORMAL; // Compile-time error: not last statement
                    standDown(); }       //                     in the block.

As the switch rules must be exhaustive, one way to achieve exhaustiveness is to throw an exception as the action in the default label.

Click here to view code image


default -> throw new IllegalArgumentException(“Not a valid value”);

Example 4.6 has been refactored to use the switch expression with the arrow notation in Example 4.7. Each action associated with a case label of a switch rule is a block of statements, where a yield statement is the last statement in a block. If this is not the case, the code will not compile.

The switch expression with the arrow notation must also be exhaustive. Again a non-exhaustive switch expression with the arrow notation will result in a compile-time error. In Example 4.7, the type of the selector expression is int, but the switch rules only cover the int values from 1 to 12. A default label is necessary to make the switch expression exhaustive, as shown at (11).

Example 4.7 Statement Blocks in a switch Expression with the Arrow Notation

Click here to view code image

public class SeasonsIV {
  enum Season { WINTER, SPRING, SUMMER, FALL }                // (1)

  public static void main(String[] args) {
    int monthNumber = 11;
    Season season = switch(monthNumber) {                     // (2)
      case 12, 1, 2 -> {                                      // (3)
        System.out.println(“Snow in the winter.”);
        yield Season.WINTER;                                  // (4)
      }
      case 3, 4, 5 -> {                                       // (5)
        System.out.println(“Green grass in the spring.”);
        yield Season.SPRING;                                  // (6)
      }
      case 6, 7, 8 -> {                                       // (7)
        System.out.println(“Sunshine in the summer.”);
        yield Season.SUMMER;                                  // (8)
      }
      case 9, 10, 11 -> {                                     // (9)
        System.out.println(“Yellow leaves in the fall.”);
        yield Season.FALL;                                    // (10)
      }
      default ->                                              // (11)
        throw new IllegalArgumentException(monthNumber + ” not a valid month.”);
    };                                                        // (12)
    System.out.println(season);
  }
}

Output from the program:

Click here to view code image

Yellow leaves in the fall.
FALL

Example 4.8 is a reworking of Example 4.7 that defines expressions as the actions in the switch rules. No yield statement is necessary or allowed in this case. The switch expression is also exhaustive.

Example 4.8 Expression Actions in a switch Expression with the Arrow Notation

Click here to view code image

public class SeasonsV {
  enum Season { WINTER, SPRING, SUMMER, FALL }                    // (1)
  public static void main(String[] args) {
    int monthNumber = 11;
    Season season = switch(monthNumber) {                         // (2)
      case 12,  1,  2 -> Season.WINTER;                           // (3)
      case  3,  4,  5 -> Season.SPRING;                           // (4)
      case  6,  7,  8 -> Season.SUMMER;                           // (5)
      case  9, 10, 11 -> Season.FALL;                             // (6)
      default         -> throw new IllegalArgumentException(monthNumber +
                                                           ” not a valid month.”);
    };
    System.out.println(season);
  }
}

Output from the program:

FALL

The switch expression can only evaluate to a single value. Multiple values can be returned by constructing an object with the required values and returning the object as a result of evaluating the switch expression. Record classes are particularly suited for this purpose (§5.14, p. 299). The switch expression at (3) in Example 4.9 returns an object of the record class SeasonInfo, defined at (2), to return the month number and the season in which it occurs.

Example 4.9 Returning Multiple Values as a Record from a switch Expression

Click here to view code image

public class SeasonsVI {
  enum Season { WINTER, SPRING, SUMMER, FALL }                              // (1)
  record SeasonInfo(int month, Season season) {}                            // (2)
  public static void main(String[] args) {
    int monthNumber = 11;
    SeasonInfo seasonInfo = switch(monthNumber) {                           // (3)
      case 12,  1,  2 -> new SeasonInfo(monthNumber, Season.WINTER);        // (4)
      case  3,  4,  5 -> new SeasonInfo(monthNumber, Season.SPRING);        // (5)
      case  6,  7,  8 -> new SeasonInfo(monthNumber, Season.SUMMER);        // (6)
      case  9, 10, 11 -> new SeasonInfo(monthNumber, Season.FALL);          // (7)
      default         -> throw new IllegalArgumentException(monthNumber +
                                                           ” not a valid month.”);
    };
    System.out.println(seasonInfo);
  }
}

Output from the program:

Click here to view code image SeasonInfo[month=11, season=FALL]