1. O que há de novo no switch
Se por acaso você programou em Java antes da versão 14, o switch parecia mais ou menos assim:
switch (day)
{
case MONDAY:
System.out.println("Início da semana!");
break;
case FRIDAY:
System.out.println("Sexta-feira, oba!");
break;
default:
System.out.println("Dia comum.");
break;
}
Nada demais, mas:
- É preciso não esquecer o break (senão vamos “cair” no próximo case).
- Muito código repetitivo.
- Se você quiser retornar um valor, precisa declarar uma variável antecipadamente e atribuir a ela dentro de cada case.
Java 14+ decidiu: chega disso! É hora de tornar o switch mais conveniente e moderno.
Principais novidades:
- O switch virou expressão, não apenas instrução — agora ele pode retornar um valor.
- Nova sintaxe com seta -> em vez de dois-pontos e break.
- Vários case separados por vírgula — para lógica idêntica.
- O compilador verifica se todos os casos foram cobertos (especialmente com enum).
- Sem risco de “queda” (fall-through) — agora isso só é possível de forma explícita.
2. Sintaxe das expressões switch
switch (znachenie)
{
case A, B -> rezul’tat1;
case C -> {
// várias ações
yield rezul’tat2;
}
default -> rezul’tatPoUmolchaniyu;
}
-> e
yield
Exemplo básico
Vamos direto ao ponto. Veja como agora é possível retornar um valor de um switch:
DayOfWeek day = DayOfWeek.MONDAY;
String message = switch (day)
{
case MONDAY, FRIDAY, SUNDAY -> "Semana curta ou dia de folga!";
case TUESDAY -> "Terça-feira — dia puxado.";
case WEDNESDAY, THURSDAY -> "Meio da semana!";
case SATURDAY -> "Viva, sábado!";
// É obrigatório ter default, se nem todos os casos forem cobertos
default -> "Um dia meio estranho...";
};
System.out.println(message);
O que está acontecendo aqui:
- switch (day) — uma expressão que retorna um valor.
- Após a seta -> vem o resultado para aquele case.
- Vários case podem ser agrupados com vírgula.
- Não há nenhum break — o Java já sabe onde a ramificação termina.
- É possível atribuir o resultado diretamente à variável message.
Exemplo com números
int code = 404;
String result = switch (code)
{
case 200 -> "OK";
case 400, 404 -> "Erro do cliente";
case 500 -> "Erro do servidor";
default -> "Código desconhecido";
};
System.out.println(result);
Exemplo com strings
String command = "start";
String status = switch (command)
{
case "start" -> "Iniciando!";
case "stop" -> "Parando!";
case "pause" -> "Pausa...";
default -> "Comando desconhecido";
};
System.out.println(status);
Usando um bloco com yield
Às vezes queremos executar várias ações para um único case (por exemplo, fazer um cálculo mais complexo ou registrar logs). Para isso, podemos usar um bloco { ... } e a palavra-chave yield:
int n = 7;
String parity = switch (n % 2)
{
case 0 -> "Par";
case 1 ->
{
System.out.println("Número ímpar detectado: " + n);
yield "Ímpar";
}
default -> "Algo estranho";
};
System.out.println(parity);
Importante: no bloco precisa haver um yield, que retorna o valor para aquele case.
3. Vantagens da nova sintaxe
Não é necessário usar break
No switch clássico, esquecer o break é fonte de dor e bugs misteriosos. Na nova sintaxe, break não é necessário: cada ramificação termina automaticamente.
O compilador verifica a cobertura de todos os casos
Se você usa enum e não cobriu todos os valores, o compilador não permitirá compilar o projeto sem default. Isso torna o código mais confiável.
Sem “queda” (fall-through)
No switch clássico, se você esquecer o break, a execução “cai” no próximo case. Na nova sintaxe isso é impossível (a não ser que você use um bloco com instruções e escreva explicitamente break — mas aqui ele não é necessário).
Código mais compacto e legível
Compare:
Antes:
String result;
switch (status) {
case "OK":
result = "Tudo bem";
break;
case "ERROR":
result = "Erro";
break;
default:
result = "Desconhecido";
break;
}
Depois:
String result = switch (status) {
case "OK" -> "Tudo bem";
case "ERROR" -> "Erro";
default -> "Desconhecido";
};
Vários case — uma única lógica
case MONDAY, FRIDAY, SUNDAY -> "Dia de folga ou dia curto!";
4. Comparação com o switch clássico
| Característica | switch clássico | novo switch |
|---|---|---|
| break é obrigatório | Sim | Não |
| Queda (fall-through) | Sim | Não |
| Pode retornar valor | Não (apenas via variável) | Sim (expressão) |
| Vários case separados por vírgula | Não | Sim |
| Verificação de todos os casos | Não | Sim (especialmente com enum) |
| Compacidade | Muito código | Curto e claro |
| Uso com enum e strings | Sim | Sim |
5. Compatibilidade com enum e strings
Exemplo com enum
Suponha que temos um enum:
enum DayOfWeek
{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Usando-o no novo switch:
DayOfWeek today = DayOfWeek.WEDNESDAY;
String mood = switch (today)
{
case MONDAY -> "Difícil levantar...";
case FRIDAY -> "Fim de semana chegando!";
case SATURDAY, SUNDAY -> "Viva, descanso!";
default -> "Dia de trabalho.";
};
System.out.println(mood);
Exemplo com String
String season = "summer";
String activity = switch (season)
{
case "winter" -> "Patinar no gelo";
case "summer" -> "Nadar no lago";
case "autumn" -> "Colher cogumelos";
case "spring" -> "Ouvir o canto dos pássaros";
default -> "Estação desconhecida";
};
System.out.println(activity);
6. Reescrevendo o switch antigo no novo estilo
Antes:
int day = 3;
String dayName;
switch (day)
{
case 1:
dayName = "Segunda-feira";
break;
case 2:
dayName = "Terça-feira";
break;
case 3:
dayName = "Quarta-feira";
break;
default:
dayName = "Dia desconhecido";
break;
}
System.out.println(dayName);
Depois:
int day = 3;
String dayName = switch (day)
{
case 1 -> "Segunda-feira";
case 2 -> "Terça-feira";
case 3 -> "Quarta-feira";
default -> "Dia desconhecido";
};
System.out.println(dayName);
Mais um exemplo: vários case — uma única lógica
int score = 5;
String grade = switch (score)
{
case 5, 6, 7 -> "Bom";
case 8, 9, 10 -> "Excelente";
default -> "Precisa se esforçar";
};
System.out.println(grade);
7. Erros comuns e particularidades
Erro nº 1: ausência de default quando nem todos os casos são cobertos. Se você usa uma switch-expressão com um tipo que pode ter valores fora dos case listados (por exemplo, com int ou String), o compilador exigirá um default. Para enum, se você não cobrir todos os valores, o default também é obrigatório.
Erro nº 2: esqueceu o yield no bloco. Se usar chaves para um case (precisa executar várias ações), não se esqueça do yield — sem ele o compilador emitirá o erro: "Missing yield statement".
Erro nº 3: incompatibilidade de tipos. Todos os ramos de uma switch-expressão devem retornar valores do mesmo tipo; caso contrário, o compilador não permitirá o código.
Erro nº 4: duplicação de valores de case. Indicar o mesmo case duas vezes não é permitido — o compilador reportará erro imediatamente.
GO TO FULL VERSION