JAX London Blog

Java 12 Tutorial: How the new switch expressions work

Jun 17, 2019

The switch case expressions in Java go back pretty much to the beginnings of the programming language. It was basically a compromise in language design to make it easier for C++ developers to switch to Java. Relics like break and fall-through were not very intuitive and caused a lot of errors. In addition, the case statement was very limited regarding the notation of the values. Fortunately, this all changes with Java 12. The syntax has been slightly modified to allow specifying one expression and multiple values. In this way, case differences can be formulated much more elegantly.

The new switch expressions in Java 12

An example of this new language feature in Java 12 is the mapping of weekdays to their textual length. Let’s first analyze why an extension and modification in the syntax and behavior of switch make sense. What were the previous weaknesses of switch? For clarification, in Listing 1 we will look at how you would formulate the mapping before Java 12.

Listing 1

DayOfWeek day = DayOfWeek.FRIDAY;

int numLetters = -1;

switch (day)
{
  case MONDAY:
  case FRIDAY:
  case SUNDAY:
    numLetters = 6;
    break;
  case TUESDAY:
    numLetters = 7;
      break;
  case THURSDAY:
  case SATURDAY:
    numLetters = 8;
    break;
  case WEDNESDAY:
    numLetters = 9;
    break;
};

Let’s take a critical look at this source code. First of all, the shown construct is not very elegant and quite long. The multiple specification of values is also rather clumsy. Worse still: A break is needed so that the processing runs without surprises and no fall-through occurs. We also need to set the (artificial) auxiliary variable correctly in each branch. So how can we do this better?

Syntax extensions with Java 12: In Java 12, “switch expressions” have been added as preview feature, which make it much easier to formulate case distinctions. In Listing 2, the intuitive syntax is clearly visible:

Listing 2

public static void switchWithReturnAndMultipleValues();
{
  DayOfWeek day = DayOfWeek.FRIDAY;

  int numLetters = switch (day)
  {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY -> 7;
    case THURSDAY, SATURDAY -> 8;
    case WEDNESDAY -> 9;
};
}

This example shows the following syntactical innovations: First, the notation of the case statement changes. In addition to the obvious arrow instead of the colon, several values can now be listed. It is particularly remarkable that we no longer need a break: The instructions behind the arrow are only executed specifically for the case, and there is no fall-through for this syntax. Finally, the switch can now return a value, thus avoiding the definition of auxiliary variables.

Enabling the Java 12 syntax extensions: Since the switch expressions are unfortunately not a final feature, you have to specify the command line parameter -enable-preview when compiling and executing the program.

Java 12: Syntax variants for “switch”

While the mentioned syntax changes alone are a great enhancement, you can enjoy even further improved variants of switch: assignments in lambda expressions and “break” with a return value.

Assignments in lambda: In the first example for the Java 12 syntax, only one value was returned on the right side. However, it is still possible to make an assignment or method calls, of course still without the need for a break (Listing 3).

Listing 3

public static void switchAssignment()
{
  final int value = 2;
  String numericString;

  switch (value)
  {
    case 1 -> numericString = "one";
    case 2 -> numericString = "two";
    case 3 -> numericString = "three";
    default -> numericString = "N/A";
  }

  System.out.println("value:" + value + " as string: " + numericString);
}

“break” with a return value: Anyone who wants to do a Java certification will certainly appreciate another variant of the syntax. Let’s return to the previous syntax. We now want to map names of colors to their number of letters – shown here deliberately with a small mistake to demonstrate fall-through (Listing 4).

Listing 4

Color color = Color.GREEN;
int numOfChars;

switch (color)
{
  case RED: numOfChars = 3; break;
  case BLUE: numOfChars = 4; break;
  case GREEN: numOfChars = 5; /* break; UPS: FALL-THROUGH */
  case YELLOW: numOfChars = 6; break;
  case ORANGE: numOfChars = 6; break;
  default: numOfChars = -1;
}

System.out.println("OLD: " + numOfChars);

In this example, you can see the disadvantages of the old syntax, which is a bit cumbersome to use and makes the fall-through hardly visible. The need to define the auxiliary variable is another beauty flaw. Let’s see how Java 12 works better.

Implementation with Java 12: The listing with Java 12 shown below is quite close to the old syntax, but with dedicated improvements: As a rather minimal variation, you can note a return value behind the break. In addition, several values can be listed in case. This results in the more readable variant shown in Listing 5.

Listing 5

public static void switchBreakReturnsValue()
{

  Color color = Color.GREEN;

  int numOfChars = switch (color)
  {
    case RED: break 3;
    case BLUE: break 4;
    case GREEN: break 5;
    case YELLOW, ORANGE: break 6;
    default: break -1;
  };
  System.out.println("color:" + color + " ==> " + numOfChars);
}

This example shows the advantages of the syntax. Although this is very similar to the previous variant, there are some simplifications and improvements. For one thing, you no longer need an artificial auxiliary variable, but can return a value with break, which stops processing there, similar to the return of a method. Finally, you can now specify multiple values in one case, which allows a more compact notation.

JOIN +1000 SOFTWARE INNOVATORS.
LEARN MORE ABOUT JAX LONDON 2019:

Adjustments for build tools and IDEs

To demonstrate the effects of Java 12 on build tools and IDEs, we use a simple example application with the following directory structure:

Java12Examples
|-- build.gradle
|-- pom.xml
‘-- src
  ‘-- main
    ‘-- java
      ‘-- java12
        ‘-- SwitchExample.java
 

The methods of the SwitchExample class have already been explained in the previous sections. There we can find some variants of the new syntax of the switch statement.

Java 12 with Gradle: For Java 12, especially for trying out the new syntax with switch, you need a current Gradle 5.1 (or newer) and some suitable information in the file build.gradle (Listing 6).

Listing 6

apply plugin: ’java’
apply plugin: ’eclipse’

sourceCompatibility=12
targetCompatibility=12

repositories
{
  jcenter();
}

// Aktivierung von switch preview
tasks.withType(JavaCompile) {
  options.compilerArgs += ["--enable-preview"]
}

Then we can build a corresponding JAR as usual with gradle clean assemble and start the class SwitchExample as follows: java -enable-preview -cp build/libs/Java12Examples.jar java12.SwitchExample. In both cases, it is important to specify the command line parameter -enable-preview, because this is the only way to start the program.

Java 12 with Maven: For Java 12 you need a current Maven 3.6.0 and the Maven Compiler Plugin version 3.8.0. Then you can enter the information shown in Listing 7 in the pom.xml:

Listing 7

<plugins>
  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.0</version>
    <configuration>
      <source>12</source>
      <target>12</target>

      <!- - Wichtig für Java 12 Syntax-Neuerungen ->
      <compilerArgs>--enable-preview</compilerArgs>
    </configuration>	
  </plugin>
</plugins>

With these modifications, you can run a Maven build with mvn clean package. Now we want to see the new switch functionality in action and enter the following:

java --enable-preview -cp target/SimpleJdk12Application-1.0.0-SNAPSHOT.jar
java12.SwitchExample

This starts the application as expected.

Conclusion

The joy over the new features in Java 12 is lessened because the raw string literals didn’t make it into the release. While the improvements in the switch-case area are very pleasant, they are almost overdue. Unfortunately, they are only integrated as preview and have to be activated via -enable-preview.

JAX London sessions by Michael Inden:

Behind the Tracks

Software Architecture & Design
Software innovation & more
Microservices
Architecture structure & more
Agile & Communication
Methodologies & more
DevOps & Continuous Delivery
Delivery Pipelines, Testing & more
Big Data & Machine Learning
Saving, processing & more