Sentencia switch en Java
Usa la sentencia switch en Java para ramificar por valores, con etiquetas case, break, default y comportamiento de fall-through.
Cuando necesitas comparar un solo valor contra muchas posibilidades, una larga cadena if/else if se vuelve rápidamente confusa. La sentencia switch es la alternativa compacta de Java — lee el valor una vez, salta a la case correspondiente y ejecuta su bloque.
Sintaxis básica
switch (value) {
case label1:
// body
break;
case label2:
// body
break;
default:
// body
break;
}Un pequeño ejemplo:
int day = 3;
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
default:
System.out.println("Other");
break;
}El switch salta a case 3:, imprime Wednesday, llega al break y sale.
El break es esencial
Sin break, la ejecución cae al siguiente caso (fall-through), incluso si su etiqueta no coincide. Esta es una característica deliberada del switch de estilo C, pero es fuente de innumerables errores en el código Java:
switch (day) {
case 1:
System.out.println("Monday");
// no break!
case 2:
System.out.println("Tuesday");
break;
}Cuando day == 1, esto imprime tanto Monday como Tuesday. Siempre agrega break a menos que intencionalmente desees el fall-through.
Fall-through intencional
A veces el fall-through es exactamente lo que quieres — agrupar múltiples etiquetas bajo el mismo bloque:
switch (day) {
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("Weekday");
break;
case 6:
case 7:
System.out.println("Weekend");
break;
}Cuando haces esto a propósito, agrega un comentario // fall through para que los revisores no crean que olvidaste un break. (La nueva sintaxis de expresión switch — tratada en el siguiente capítulo — elimina completamente este problema.)
¿Qué puede ser un valor de switch?
Un switch tradicional acepta:
- Todos los tipos enteros:
byte,short,int,char - Sus envoltorios boxed:
Byte,Short,Integer,Character String(desde Java 7)- Constantes
enum
No permitidos: long, float, double, boolean ni objetos arbitrarios. Para esos, usa if/else.
String role = "admin";
switch (role) {
case "admin":
System.out.println("Full access");
break;
case "editor":
System.out.println("Write access");
break;
case "viewer":
System.out.println("Read access");
break;
default:
System.out.println("No access");
break;
}La comparación de string en un switch usa la semántica de String.equals — distingue mayúsculas de minúsculas. Un punto delicado: hacer switch sobre un String (o cualquier valor boxed/enum) que sea null lanza un NullPointerException. Verifica si es null antes del switch, o manéjalo en un guard:
if (role == null) {
System.out.println("No role");
} else {
switch (role) {
case "admin":
System.out.println("Full access");
break;
// ...
}
}default — el caso general
default se ejecuta cuando ningún case coincide. No es obligatorio, pero incluirlo es una buena práctica; hace explícito el comportamiento para valores inesperados.
default no tiene que ir al final. Por convención se coloca al fondo, pero el compilador lo acepta en cualquier lugar — la ejecución cae a través de él igual que con cualquier otro case si olvidas el break.
Reglas a tener en cuenta
Un par de reglas impuestas por el compilador suelen confundir a las personas:
- Las etiquetas de case deben ser constantes en tiempo de compilación. Puedes usar literales (
case 3:), constantesfinalo nombres deenum— pero no una variable ni una llamada a método.case x:dondexes una variable no-final no compilará. - Las etiquetas deben ser únicas. Dos entradas
case 3:en el mismo switch son un error de compilación. - Todos los casos comparten un mismo ámbito. Una variable declarada en un case es visible en los demás, lo que puede causar conflictos. Envuelve el cuerpo de un case con llaves
{ }cuando necesites una variable local con ámbito solo para ese case:
switch (day) {
case 1: {
int hours = 8;
System.out.println(hours);
break;
}
case 2:
// `hours` is not visible here
break;
}Switch con enum
enum y switch son una pareja natural. Dentro de un switch sobre un valor enum, no necesitas calificar el nombre de la constante:
enum Status { PENDING, ACTIVE, DONE }
Status s = Status.ACTIVE;
switch (s) {
case PENDING: // not Status.PENDING
System.out.println("Waiting...");
break;
case ACTIVE:
System.out.println("In progress");
break;
case DONE:
System.out.println("Finished");
break;
}Un ejemplo práctico
¿Qué sigue?
Java 14 introdujo las expresiones switch, que devuelven un valor, eliminan el fall-through y admiten casos con múltiples etiquetas — el código Java moderno las prefiere cuando se apunta a Java 14 o versiones más recientes.