W3docs

Expresiones switch en Java

Expresiones switch modernas en Java con sintaxis de flecha, yield y coincidencia de patrones exhaustiva.

Java 14 promovió las expresiones switch como característica estándar del lenguaje. Se construyen sobre la sentencia switch tradicional con tres grandes mejoras: producen un valor, usan una sintaxis de flecha más limpia y hacen imposible el fall-through. Si usas Java 14 o una versión más reciente, dales preferencia.

Este capítulo cubre la sintaxis de flecha, la palabra clave yield para cuerpos de bloque, la verificación de exhaustividad y la coincidencia de patrones basada en tipos que se convirtió en estándar en Java 21. Al final sabrás cuándo conviene usar una expresión switch en lugar de una cadena if/else.

Sentencia vs. expresión

La switch tradicional es una sentencia: hace algo (ejecuta efectos secundarios) pero no produce un valor. Una expresión switch se evalúa a un valor que puedes asignar, retornar o pasar a un método. Esa única diferencia impulsa todo lo demás en esta página: porque el resultado se usa, el compilador puede exigir que cada rama produzca un valor y que ninguna entrada quede sin manejar.

Sintaxis de forma con flecha

String day = "TUE";

String label = switch (day) {
  case "MON", "TUE", "WED", "THU", "FRI" -> "weekday";
  case "SAT", "SUN" -> "weekend";
  default -> "unknown";
};

Tres cosas a notar:

  1. El switch completo es una expresión: se evalúa a un valor que puedes asignar (observa el ; al final).
  2. Cada caso usa -> en lugar de :. El lado derecho es una sola sentencia o expresión.
  3. Se permiten múltiples etiquetas en un mismo caso, separadas por comas. Sin break, sin fall-through.

Cuerpos de bloque con yield

Si un caso necesita varias sentencias, usa un bloque — y dentro del bloque, devuelve el valor con yield:

int score = 78;

String grade = switch (score / 10) {
  case 10, 9 -> "A";
  case 8 -> "B";
  case 7 -> {
    System.out.println("close to B");
    yield "C";
  }
  case 6 -> "D";
  default -> "F";
};

yield es como return, pero para la expresión switch: establece el valor de este switch y sale del caso. (No lo confundas con return, que saldría del método que lo contiene.)

Solo necesitas yield dentro de un bloque ({ ... }). Un caso de expresión única como case 8 -> "B"; ya devuelve su valor directamente, por lo que agregar yield allí sería un error de compilación.

Información

yield es una palabra clave contextual: solo actúa como palabra clave dentro de un bloque switch. El código que usaba yield como nombre de variable o de método antes de Java 14 sigue compilando, por lo que adoptar expresiones switch nunca rompe los identificadores existentes.

Las sentencias siguen funcionando

También puedes usar la sintaxis de flecha para efectos secundarios; en ese caso es una sentencia, no una expresión:

switch (day) {
  case "MON", "TUE", "WED", "THU", "FRI" -> System.out.println("weekday");
  case "SAT", "SUN" -> System.out.println("weekend");
  default -> System.out.println("unknown");
}

La ventaja sobre la forma antigua: sin break, sin errores de fall-through, además de los casos con múltiples etiquetas descritos arriba.

Exhaustividad

Cuando una expresión switch asigna a una variable, el compilador requiere que cada posible entrada produzca un valor. Para un enum, eso significa cubrir todas las constantes o proporcionar un default:

enum Status { PENDING, ACTIVE, DONE }

Status s = Status.ACTIVE;

String label = switch (s) {
  case PENDING -> "waiting";
  case ACTIVE  -> "running";
  case DONE    -> "complete";
};   // no default needed — all enum values are covered

Si luego agregas una nueva constante al enum y olvidas actualizar el switch, el compilador te lo dirá. Esa es una garantía de corrección que no obtienes con if/else.

Coincidencia de patrones (Java 21+)

Java 21 convirtió en estándar la coincidencia de patrones para switch. Puedes hacer switch sobre el tipo de un valor y vincularlo a una variable tipada dentro del caso:

Object o = 42;

String description = switch (o) {
  case Integer i when i < 0 -> "negative int: " + i;
  case Integer i             -> "non-negative int: " + i;
  case String s              -> "string of length " + s.length();
  case null                  -> "null value";
  default                    -> "something else";
};

La cláusula when es un guard: restringe un caso más aún con una condición boolean. Esto reemplaza muchas cadenas de instanceof, y se combina naturalmente con las características más amplias de coincidencia de patrones.

Dos reglas a tener en cuenta:

  • Un switch tradicional rechaza un selector null con una NullPointerException. Un switch de patrones puede incluir un case null explícito: sin él, un null sigue lanzando la excepción. Ya no es posible pasar por alto que null llega al switch silenciosamente.
  • Los casos se evalúan de arriba a abajo, así que ordénalos de más específico a más general. El case Integer i when i < 0 con guard debe ir antes que el simple case Integer i, o el caso sin guard absorbería primero todos los enteros.

Un ejemplo completo

java— editable, runs on the server

¿Qué sigue?

Hemos cubierto los condicionales. A continuación vienen los bucles: el bucle while es el más sencillo de todos.

Práctica

Práctica
Dentro de una expresión switch de forma con flecha con un cuerpo de bloque, ¿qué palabra clave devuelve el valor de ese caso?
Dentro de una expresión switch de forma con flecha con un cuerpo de bloque, ¿qué palabra clave devuelve el valor de ese caso?
Was this page helpful?