Switch expression en Java 17

Advertisements

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).

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;
}

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

Advertisements

Leave a Reply

Your email address will not be published.