Friday, September 7, 2018

Playing with JDK 12's Switch Expressions

In the blog post "JDK Language Feature Preview in Action: Switch Expressions," I discussed how JEP 325 ["Switch Expressions (Preview)"] is an early application of a designated "preview language feature" as spelled out by JEP 12 ["Preview Language and VM Features"]. JEP 325 is targeted for JDK 12. Even better, the Early Access Builds for JDK 12 already provide support for this preview language feature!

I've been excited about the possibilities associated with switch expressions as demonstrated in my previous blog posts "Switch Expressions Coming to Java?", "Enhancing Java switch Statement with Introduction of switch Expression", and the aforementioned "JDK Language Feature Preview in Action: Switch Expressions." The JDK 12 Early-Access Builds make it really easy to start experimenting with this preview language feature and I demonstrate this using JDK 12 Early Access Build 10 (2018/9/6) [latest build as of this writing].

Rather than expending any extra effort in coming up with my own creative example of a switch expression, I'm going to borrow one of the examples provided currently in the JEP 325 itself (early in the "Description" section). This example is really an enhanced switch statement rather than a switch expression, but it requires the same language preview support and is part of that feature. The code listing for that adapted example is shown next.

package dustin.examples.jdk12.switchexp;

public class SwitchExpressionsDemo
{
   /**
    * This example is adopted from the JEP 325 text
    * (http://openjdk.java.net/jeps/325).
    *
    * @param k Value to be switched upon.
    */
   static void howMany(final int k)
   {
      switch (k)
      {
         case 1 -> System.out.println("one");
         case 2 -> System.out.println("two");
         case 3 -> System.out.println("many");
      }
   }

   /**
    * Execute demonstration discussed in JEP 325 using custom
    * method {@link #howMany(int)}.
    */
   public static void demonstrateHowMany()
   {
      howMany(1);
      howMany(2);
      howMany(3);
   }

   public static void main(final String[] arguments)
   {
      demonstrateHowMany();
   }
}

The version of this class shown above can be found on GitHub.

When I attempt to compile the above code with the JDK 12 javac compiler without any special flags, I see the error message: "error: switch rules are a preview feature and are disabled by default." That error message also provides the helpful hint, "(use --enable-preview to enable switch rules)".

Passing the --enable-preview flag to the JDK 12 javac compiler gets me past the error just shown, but then I'm reminded that the --enable-preview flag should be used in conjunction with either the -source flag or the --release flag. The error message clearly states, "error: --enable-preview must be used with either -source or --release".

I elected to go with the --release 12 flag used in conjunction with --enable-preview and that allows the enhanced switch statement demonstration example to compile.

The enhanced switch statement example compiles with the --enable-preview and --release 12 options passed to the JDK 12 javac compiler, but as the output in the last screen snapshot indicates, there is a message that states that the compiled class "uses preview language features" and advises, "Recompile with -Xlint:preview for details." The next screen snapshot demonstrates the results of specifying -Xlint:preview:

Passing the -Xlint:preview flag to the JDK 12 javac compiler when compiling the switch expressions demonstration example led to three warning messages pointing to the specific lines of code using the switch expression (-> syntax) and stating, "warning: [preview] switch rules are a preview feature and may be removed in a future release."

With the enhanced switch statement code compiling, it's now time to try running the code. If the JDK 12 java launcher is invoked without any flags indicating use of the preview feature, an error message is presented: "java.lang.UnsupportedClassVersionError: Preview features are not enabled for ... Try running with '--enable-preview'."

When --enable-preview is passed to the JDK 12 java launcher, the demonstration runs successfully as depicted in the next screen snapshot.

When the output shown in the the last screen snapshot is compared to the source code of the enhanced switch statement demonstration spelled out in the beginning of this post, some observations can quickly be made. Perhaps most noticeable is that there were no break statements in the example, but no fall-through occurred despite the absence of break statements. This is exactly what JEP 325 states should happen for switch expressions and for enhanced switch statements: "If a label is matched, then only the expression or statement to the right of an arrow label is executed; there is no fall through." The presence of the "arrow" (->) indicates we're using a switch expression or enhanced switch statement where the expression or statement will be completely resolved by what lies to the right of the "arrow" (and so no explicit break is required). The presence of the "colon" (instead of the "arrow") with an associated break in a switch expression or enhanced switch statement allows for multiple lines to be specified.

There is much more to see and try related to switch expressions and enhanced switch statements. However, this post has focused on introducing the availability of switch expression and enhanced switch statement support in JDK 12 early access builds and has provided a simple example of that support. It's exciting to start playing with Java switch expressions and enhanced switch statements! It's also exciting to think about a world without switch fallthrough! This will only be a "preview" feature for JDK 12, but I'm looking forward to the beginning of the end for switch fallthrough.

No comments: