Java 17 ha llegado con algunas características interesantes para el lenguaje, una de ellas son las expresiones switch. Tal vez, alguien se pregunte ¿Pero si el switch ya existe en Java? y la respuesta es sí, como una sentencia (statement) que solamente evalúa un dato pero no retorna valor. Esa es la diferencia, al ser una expresión puede retornar valores, además incluir patrones a los case
.
Es importante indicar que las expresiones switch han estado en el lenguaje desde versiones anteriores de Java, iniciando en Java 12 en modo preview y recibiendo constantes mejoras con las siguientes versiones de Java. Es hasta Java 17 que se encuentra disponible en una version estable de soporte largo (LTS).
Este es el primer paso hacia un estilo de programación más declarativo y “null-safe”, permitiendo una mejor manera de expresar y modelar datos, reconociendo la semántica del modelo de datos por medio de patrones. Mejorando de forma definitiva la legibilidad de nuestro código, evitando if anidados para muchas circunstancia, y proporcionando características que vemos en otros lenguajes de programación.
Tomemos como referencia el siguiente código, con varios if/else if
e 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; }
El código anterior se puede transformar con una expresión switch de la siguiente manera
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
Ahora bien, ¿Cómo van a co-existir el “switch expression” y el “switch statement”? La primera diferencia está en el operador utilizado luego del case
, la expresión utiliza una flecha (arrow) ->
mientras que el “statement” continua usando el operador :
(dos puntos).
//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; }
Se puede notar que en los “switch statement” aún es necesario utilizar la sentencia break
para terminar el flujo del switch, es decir que si no se indica break
seguirá ejecutando los bloques de código de los siguientes labels. Por otro lado, en la expresión switch, solamente se ejecuta bloque de código del patrón o valor con el que hizo “match”.
Cabe destacar, que tanto la sentencia como la expresión siguen funcionando con valores exactos o constantes, no solamente con patrones a los que hace match. Por ejemplo, el siguiente código sigue siendo funcional.
//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(); }
Soporte del null
Tradicionalmente el switch lanza un NullPointerException
cuando el valor el nulo. Este comportamiento sigue presente para los switch statements existentes, que no hacen uso de patrones. Sin embargo, para hacer más amigable las nuevas características del switch (tanto el statement como la expresión) permite null
como parte del patrón.
switch (o) { case null -> System.out.println("null!"); case String s -> System.out.println("String"); default -> System.out.println("Something else"); }
Guarded Pattern
Este es una característica que he visto en otros lenguajes y me parece muy acertado que se haya agregado en Java también. Un “guarded pattern” es una condición que forma parte de expresión que debe hacer match y es precedida del operador &&
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
Hay muchas otras características del switch que no son enumeradas en este artículo, sin embargo, se trata de mostrar las principales, que considero pueden proporcionar una gran mejora en usabilidad a nuestro código.
Definitivamente, Java como lenguaje sigue evolucionando y proporcionando características que simplificarán más nuestro código y haciendo que se mantenga a la par de muchos otros lenguajes nuevos que suelen son tendencia en este momento.
Referencias
- https://openjdk.java.net/jeps/406
- https://www.infoworld.com/article/3606833/jdk-17-the-new-features-in-java-17.html