DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. Java
  4. JDK 12 Switch Expression Encountering Unanticipated Enum Value

JDK 12 Switch Expression Encountering Unanticipated Enum Value

Want to learn more about handing the unanticipated enum value in the JDK switch expressions? Check out this post to learn more about how to handle switch expressions.

Dustin Marx user avatar by
Dustin Marx
·
Sep. 14, 18 · Tutorial
Like (3)
Save
Tweet
Share
9.21K Views

Join the DZone community and get the full member experience.

Join For Free

As I wrote about in my post "Playing with JDK 12's Switch Expressions," the JDK 12 Early Access Builds have made it easy to experiment with the implementation of JEP 325 ["Switch Expressions (Preview)"]. My post "JDK 12: Switch Statements/Expressions in Action" used code examples to demonstrate the core features and characteristics of the enhanced switch statement and the new switch expression. In this post, I look at a special case explicitly called out in JEP 325 related to a runtime addition to an enum used in a switchexpression.

Because a switch expression returns a value, it is necessary that all possible cases the switch might encounter are handled via a case (or covered by a default for those not explicitly associated with a case). JEP 325 states the following:

"The cases of a switch expression must be exhaustive; for any possible value there must be a matching switch label. In practice this normally means simply that a default clause is required; however, in the case of an enum switch expression that covers all known cases (and eventually, switch expressions over sealed types), a default clause can be inserted by the compiler that indicates that the enum definition has changed between compile-time and runtime. (This is what developers do by hand today, but having the compiler insert it is both less intrusive and likely to have a more descriptive error message than the ones written by hand.)"

I have written code similar to that described in JEP 325 ("this is what developers do by hand today") as discussed in my blog post "Log Unexpected Switch Options." In the past, it was often wise to add logic for handling or logging switch statement options that were not explicitly called out or handled in a default. With the advent of switch expressions via JDK 12 and JEP 325, it is now required.

JEP 325 addresses the case of a switch expression on an enum and explicitly specifies how to support situations when all of an enum's values were explicitly specified in case clauses when the enum and code with the switch expression were compiled, but then more values were later added to the enum without recompiling the switch expression code using that enum.

To demonstrate this support, I will present a simple enum along with two examples based on JEP 325 and the JDK Early Access Build 10 to use that enum in a switch statement and a switch expression.

The following code listing shows a simple enum called Response that only has two values.

package dustin.examples.jdk12.switchexp;  

/** 
 * Enum representation of a response. 
 */  
public enum Response  
{  
   YES,  
   NO;  
}  


The next code listing shows a class that includes two methods that use the enum shown above. One method uses a switch statement against that enum and the other uses a switch expression against that enum.

package dustin.examples.jdk12.switchexp;  

import static java.lang.System.out;  

/** 
 * Demonstrates implicit handling of expanding enum 
 * definition related to JEP 325 switch expressions and 
 * switch statements. 
 */  
public class GrowingEnumSwitchDemo  
{  
   public static void printResponseStringFromStatement(final Response response)  
   {  
      out.println("Statement [" + response.name() + "]:");  
      switch (response)  
      {  
         case YES:  
            out.println("Si!");  
            break;  
         case NO:  
            out.println("No!");  
            break;  
      }  
   }  

   public static void printResponseStringFromExpression(final Response response)  
   {  
      out.println("Expression [" + response.name() + "]:");  
      out.println(  
         switch (response)  
         {  
            case YES -> "Si!";  
            case NO -> "No!";  
         });  
   }  

   public static void main(final String[] arguments)  
   {  
      if (arguments.length < 1)  
      {  
         out.println("Provide an appropriate 'dustin.examples.jdk12.switchexp.Response' string as an argument.");  
         System.exit(-1);  
      }  
      final String responseString = arguments[0];  
      out.println("Processing string '" + responseString + "'.");  
      final Response response = Response.valueOf(responseString);  
      printResponseStringFromStatement(response);  
      printResponseStringFromExpression(response);  
   }  
}  


The code above, which is also available on GitHub, will compile without incident, and when I execute the main function on the GrowingEnumSwitchDemo class and pass it the "YES" string, it works as expected. If I add a new value MAYBE to the Response enum and compile only that enum Java file and then run the GrowingEnumSwitchDemo.main(String[]) with string "MAYBE," I encounter an IncompatibleClassChangeError. The new Response.java listing is shown next, followed by a screen snapshot that demonstrates the issue just described once the enum only was re-compiled with a new value and run with the previously compiled calling code.

package dustin.examples.jdk12.switchexp;  

/** 
 * Enum representation of a response. 
 */  
public enum Response  
{  
   YES,  
   NO,  
   MAYBE;  
}  


The presence of the IncompatibleClassChangeError makes it obvious immediately that there is a new value on the enum not previously handled by the switch expression. This allows the developer to fix the switchexpression either by adding a case for the enum value or by adding a catch-all default. This is likely to be better than the current situation today where a switch statement using the :/break syntax will silently move on without exception message in the same situation, which is also demonstrated in the previous code listing and screen snapshot.

There are several things to like about the enhancements coming to Java via JEP 325. The "arrow" syntax allows switch expressions and switch statements to not be burdened with surprising scope issues, risk of unintentional fall-through, or need for explicit breaks. Furthermore, switch expressions, which must return a value, can be used in conjunction with enums to ensure that all enum values are always handled at compile-time, which won't compile if all enum values are not handled at compile-time, or that an error is thrown if the enum used has a value added to it and is used with the previously compiled client code.

Java (programming language) Java Development Kit

Published at DZone with permission of Dustin Marx, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Introduction to NoSQL Database
  • Data Stream Using Apache Kafka and Camel Application
  • Master Spring Boot 3 With GraalVM Native Image
  • Kubernetes-Native Development With Quarkus and Eclipse JKube

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: