Switch expression on Java 17

Advertisements

Java 17 has come up with some cool features for the language, one of which is switch expressions. Maybe someone wonders, – But, does the switch already exists in Java? and the answer is yes, as a statement that only evaluates a data but does not return a value. That is the difference, being an expression it can return values, also include patterns to the case.

It is important to note that switch expressions have been in the language since previous versions of Java, starting in Java 12 in preview mode and receiving constant improvements with the following versions of Java. It is up to Java 17 that it is available in a stable long support (LTS) release.

This is the first step towards a more declarative and “null-safe” programming style, allowing a better way to express and model data, recognizing the semantics of the data model through patterns. Definitively improving the readability of our code, avoiding nested if/elseif/else for many circumstances, and providing features that we see in other programming languages.

Let’s take the following code as reference, with some if/else if and instanceof.

static String formatter(Object o) {
    String formatted = "unknown";
    if (o instanceof Integer i) {
        formatted = String.format("int %d", i);
    } else if (o instanceof Long l) {
        formatted = String.format("long %d", l);
    } else if (o instanceof Double d) {
        formatted = String.format("double %f", d);
    } else if (o instanceof String s) {
        formatted = String.format("String %s", s);
    }
    return formatted;
}

The previous code can be converted with a switch expression.

static String formatterPatternSwitch(Object o) {
    return switch (o) {
        case Integer i -> String.format("int %d", i);
        case Long l    -> String.format("long %d", l);
        case Double d  -> String.format("double %f", d);
        case String s  -> String.format("String %s", s);
        default        -> o.toString();
    };
}

Switch Expression vs Switch Statement

Now, how are the switch expression and statement going to co-exist? The first difference is in the operator used after the case, the expression uses an arrow -> while the statement continues using the operator : (colon).

Advertisements
//Switch Expression example
switch (o) {
	case Integer i -> String.format("int %d", i);
    case Long l    -> String.format("long %d", l);
}
//Switch Statement example
switch (o) {
  case Integer i: 
    String.format("int %d", i);
    break;
  case Long l:
    String.format("long %d", l); 
    break;
}

It can be noticed that in the switch statement is still necessary to use the break statement to terminate the switch flow, in other words, if break is not indicated, it will continue executing the code blocks of the following labels. On the other hand, in the switch expression, only the code block of the matching pattern or value is executed.

It should be noted that both the sentence and the expression continue to work with exact or constant values, not only with patterns that it matches. For example, the following code is still valid.

//Switch statement 
switch (value) {
  case "A": 
    callMethod1();
    break;
  case "B": 
    callMethod2();
    break;
  default:
    callMethod3();
}
//Switch Expression
switch (value) {
  case "A"-> callMethod1();
  case "B"-> callMethod2();
  default -> callMethod3();
}

Support of null

Traditionally, the switch throws a NullPointerException when the value is null. This behavior is still present for existing switch statements, which do not make use of patterns. However, to make the new features of the switch more user-friendly (both the statement and the expression) allow null as part of the pattern.

switch (o) {
  case null     -> System.out.println("null!");
  case String s -> System.out.println("String");
  default       -> System.out.println("Something else");
}

Guarded Pattern

This is a feature that I have seen in other languages and I think it was very successful that it is being added in Java as well. The “guarded pattern” is a condition that is part of an expression that must be matched and is preceded by the && operator.

switch(value) {
  case String s && (s.length > 3) -> System.out.println("A short string");
  case String s && (s.length > 10 -> System.out.println("A medium string");
  default -> System.out.println("A long string");
}

Conclusión

There are many other features of the switch that are not listed in this article, however, it is about showing the main ones, which I believe can provide a great improvement in usability to our code.

Definitely, Java as a language continues to evolve and provide features that will further simplify our code and keep it on par with many other new languages that are trending at the moment.

References

Advertisements

Leave a Reply

Your email address will not be published. Required fields are marked *