Instrução switch em Java
Use a instrução switch em Java para ramificar por valores, com rótulos case, break, default e comportamento de fall-through.
Quando você precisa comparar um único valor contra muitas possibilidades, uma longa cadeia de if/else if rapidamente se torna confusa. A instrução switch é a alternativa compacta do Java — lê o valor uma vez, salta para o case correspondente e executa seu bloco.
Sintaxe básica
switch (value) {
case label1:
// body
break;
case label2:
// body
break;
default:
// body
break;
}Um pequeno exemplo:
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;
}O switch salta para case 3:, imprime Wednesday, encontra o break e sai.
O break é essencial
Sem o break, a execução cai para o próximo case — mesmo que seu rótulo não corresponda. Isso é um recurso deliberado do switch no estilo C, mas é a fonte de inúmeros bugs no código Java:
switch (day) {
case 1:
System.out.println("Monday");
// no break!
case 2:
System.out.println("Tuesday");
break;
}Quando day == 1, isso imprime tanto Monday quanto Tuesday. Sempre adicione break, a menos que você queira intencionalmente o fall-through.
Fall-through intencional
Às vezes o fall-through é exatamente o que você quer — agrupando múltiplos rótulos sob o mesmo bloco:
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;
}Quando você faz isso propositalmente, adicione um comentário // fall through para que os revisores não pensem que você esqueceu um break. (A nova sintaxe de expressão switch — abordada no próximo capítulo — corrige completamente esse problema.)
O que pode ser um valor de switch?
Um switch tradicional aceita:
- Todos os tipos inteiros:
byte,short,int,char - Seus wrappers boxed:
Byte,Short,Integer,Character String(desde o Java 7)- Constantes de
enum
Não permitido: long, float, double, boolean ou objetos arbitrários. Para esses, use 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;
}A comparação de String em um switch usa a semântica de String.equals — com distinção entre maiúsculas e minúsculas. Um detalhe importante: fazer switch em uma String (ou qualquer valor boxed/enum) que seja null lança uma NullPointerException. Verifique se há null antes do switch ou trate-o em uma guarda:
if (role == null) {
System.out.println("No role");
} else {
switch (role) {
case "admin":
System.out.println("Full access");
break;
// ...
}
}default — o caso coringa
default é executado quando nenhum case corresponde. Não é obrigatório, mas incluí-lo é uma boa prática; torna o comportamento para valores inesperados explícito.
default não precisa ser o último. Por convenção fica no final, mas o compilador o aceita em qualquer lugar — a execução cai para ele como qualquer outro case se você esquecer o break.
Regras para ter em mente
Algumas regras impostas pelo compilador confundem as pessoas:
- Rótulos de case devem ser constantes em tempo de compilação. Você pode usar literais (
case 3:), constantesfinalou nomes deenum— mas não uma variável ou chamada de método.case x:ondexé uma variável não-final não compila. - Rótulos devem ser únicos. Duas entradas
case 3:no mesmo switch constituem um erro de compilação. - Todos os cases compartilham um escopo. Uma variável declarada em um case é visível nos outros, o que pode gerar conflitos. Envolva o corpo de um case em chaves
{ }quando precisar de uma variável local com escopo limitado àquele case:
switch (day) {
case 1: {
int hours = 8;
System.out.println(hours);
break;
}
case 2:
// `hours` is not visible here
break;
}Switch com enum
enum e switch são uma dupla natural. Dentro de um switch sobre um valor enum, você não precisa qualificar o nome da 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;
}Um exemplo prático
O que vem a seguir
O Java 14 introduziu expressões switch, que retornam um valor, eliminam o fall-through e suportam cases com múltiplos rótulos — o código Java moderno as prefere sempre que o alvo for Java 14 ou mais recente.