Wednesday, 27 November 2019

Switch case in JDK12

Until JDK 12, a switch could only be used as a statement, where it performed an action but did not return a result. In JDK 12, a switch can now be used as an expression, meaning it returns a result that can be assigned to a variable. There were also several changes to the syntax of case statements within the switch. Let's use the example from the JEP to understand how this works.

A common idiom of using switch is to use one variable to determine how to assign a value to another variable.
int numberOfLetters;
switch(dayOfWeek) {
  case MONDAY:
  case FRIDAY:
  case SUNDAY:
    numberOfLetter = 6;
    break;
  case TUESDAY
    numberOfLetter = 7;
    break;
  case THURSDAY
  case SATURDAY
    numberOfLetter = 8;
    break;
  case WEDNESDAY
    numberOfLetter = 9;
    break;
  default:
   throw new IllegalStateException("Huh?: " + day);
}

In this example, we're using the value of dayOfWeek to assign a value to numberOfLetters. Because of the way the switch statement works, the code is more error-prone than is ideal. Firstly, if we neglect to include a break statement for each case label group, the default is to fall-through to the next label group. This can lead to some subtle and hard to find bugs.
Secondly, we must make an assignment in each case label group. In this case, we would get a compiler error if we forgot, but it is still not ideal. Our code is also quite verbose since each value of dayOfWeek must have its own case label.
Using the new case-statement syntax, we get much cleaner, less error-prone code:
int numberOfLetters = switch (dayOfWeek) {
   case MONDAY, FRIDAY, SUNDAY -> 6;
   case TUESDAY -> 7;
   case THURSDAY, SATURDAY -> 8;
   case WEDNESDAY -> 9;
   default -> throw new IllegalStateException("Huh?: " + day);
};

Now, we need to make the assignment only once (from the return value of the switch expression) and can use a comma-separated list for the case labels. Since we don't use a break statement, we also eliminate the problem of fall-through.
The syntax of the switch expression allows the use of the older-style syntax so, in JDK 12, we can write it like this:
int numberOfLetters = switch (dayOfWeek) {
  case MONDAY:
  case FRIDAY:
  case SUNDAY:
   break 6;
  case TUESDAY
   break 7;
  case THURSDAY
  case SATURDAY
   break 8;
  case WEDNESDAY
   break 9;
  default:
   throw new IllegalStateException("Huh?: " + day);
};

Feedback from the Java community indicated that overloading the use of the break to indicate the value to return could be confusing. The Java language also allows the use of break (and continue) with a label to perform a form of goto. JEP 354 changes the use of break, in this case, to yield, so in JDK 13, our code becomes:
int numberOfLetters = switch (dayOfWeek) {
  case MONDAY:
  case FRIDAY:
  case SUNDAY:
   yield 6;
  case TUESDAY
   yield 7;
  case THURSDAY
  case SATURDAY
   yield 8;
  case WEDNESDAY
   yield 9;
  default:
   throw new IllegalStateException("Huh?: " + day);
};
Here, we can see the benefit of preview features that allow a change like this to be made easily before committing the syntax to the standard.