Desde siempre, Java ha contado con la palabra clave switch para construir sentencias condicionales que nos permiten ejecutar diferentes bloques de código según el valor de una variable. Tradicionalmente, el switch funciona evaluando una variable, como por ejemplo i, y comparándola con distintos valores en cada case. Si el valor coincide con un case, se ejecuta el código asociado a ese caso.
Por ejemplo, si tenemos case 0, significa que cuando i vale 0, se ejecutará el código que sigue a ese case. Lo mismo ocurre con case 1, case 2, y así sucesivamente. También existe el default, que actúa como un caso general para cuando ninguno de los anteriores coincide. Además, podemos agrupar varios casos consecutivos, como case 3, case 4 y case 5, para que ejecuten el mismo bloque de código.
Sin embargo, el uso tradicional del switch puede ser propenso a errores, especialmente cuando olvidamos incluir la palabra clave break. Esto es crucial porque, sin el break, la ejecución no se detiene al final de un caso, sino que continúa en los siguientes casos, lo que puede provocar que se ejecuten líneas de código no deseadas y que variables se sobrescriban con valores incorrectos. Este comportamiento puede generar bugs difíciles de detectar.
Además, cuando queremos asignar un valor a una variable usando un switch clásico, el código puede volverse incómodo y repetitivo. Tenemos que declarar la variable antes del switch y asignarle valores dentro de cada caso, asegurándonos de cubrir todos los casos, incluido el default, para evitar problemas de inicialización.
Para solucionar estas limitaciones, desde Java 14 se introdujo una nueva forma de trabajar con switch llamada switch expressions. Esta nueva sintaxis permite que el switch se use como una expresión que devuelve un valor, lo que facilita asignar directamente el resultado a una variable o devolverlo desde una función.
En el switch expression moderno, en lugar de usar dos puntos : después de cada case, se utiliza una flecha ->. Esto indica que la expresión o sentencia que sigue es la que se ejecutará cuando el caso coincida. Por ejemplo:
switch (i) {
case 0 -> System.out.println("No hay datos");
case 1 -> System.out.println("Hay un dato");
case 2 -> System.out.println("Hay dos datos");
case 3, 4, 5 -> System.out.println("Hay menos de 6");
default -> System.out.println("Hay muchos datos");
}
Aquí, cada caso está asociado a una única expresión o sentencia. Si queremos ejecutar más de una sentencia para un caso, podemos usar un bloque entre llaves {} para agruparlas, y el bloque completo se considera la única expresión del caso. Por ejemplo:
switch (i) {
case 1 -> {
System.out.println("i es igual a 1");
System.out.println("Ejecutando más de una sentencia");
}
default -> System.out.println("Otro caso");
}
Lo más interesante es que podemos usar el switch expression para asignar valores directamente a variables. Por ejemplo:
String msg = switch (i) {
case 0 -> "No hay datos";
case 1 -> "Hay un dato";
case 2 -> "Hay dos datos";
case 3, 4, 5 -> "Hay menos de 6";
default -> "Hay muchos datos";
};
Fíjate que el switch termina con un punto y coma, porque ahora es una expresión que devuelve un valor. Esto simplifica mucho el código y evita errores comunes del switch clásico.
Cuando usamos bloques con llaves para ejecutar varias sentencias dentro de un caso, y queremos devolver un valor, no podemos simplemente poner la expresión al final. En estos casos, Java introduce la palabra clave yield, que indica qué valor debe devolver ese bloque. Por ejemplo:
String msg = switch (i) {
case 1 -> {
System.out.println("i es igual a 1");
yield "Hay un dato";
}
default -> "Otro caso";
};
Aquí, el bloque ejecuta dos sentencias: un println y luego devuelve el valor "Hay un dato" con yield. Esto permite que el switch expression mantenga la capacidad de devolver valores incluso cuando el código de un caso es más complejo.
Este nuevo enfoque no solo mejora la legibilidad y reduce errores, sino que también abre la puerta a características más avanzadas, como el pattern matching en switch, que ha sido incorporado en versiones recientes de Java para hacer el lenguaje más moderno y expresivo, tomando ideas de lenguajes como Kotlin.
En definitiva, el switch expression nos permite escribir código más limpio y seguro, facilitando asignaciones directas y evitando los problemas clásicos del switch tradicional, como olvidos de break o variables sin inicializar. Además, la palabra clave yield nos da flexibilidad para devolver valores desde bloques complejos dentro del switch. Esto representa un paso importante hacia un Java más moderno y expresivo.