W3docs

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:), constantes final ou nomes de enum — mas não uma variável ou chamada de método. case x: onde x é 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

java— editable, runs on the server

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.

Prática

Prática
Em um switch tradicional do Java, o que acontece se você omitir o break em um bloco case?
Em um switch tradicional do Java, o que acontece se você omitir o break em um bloco case?
Was this page helpful?