switch, case și default în Java

Controlul execuției Java 1.0 (String din Java 7, case cu săgeată din Java 14)

Alege ce cod se execută comparând o valoare cu mai multe constante case; default tratează orice altă valoare.

Sintaxă
switch (valoare) {
    case 1 -> instructiune;
    case 2, 3 -> { ... }
    default -> altceva;
}

// forma veche, cu break
switch (valoare) {
    case 1:
        ...
        break;
    default:
        ...
}

Ce face switch, case și default

switch compară o valoare (întreg, char, String, enum sau, din Java 21, orice obiect cu pattern-uri) cu constantele din ramurile case. Ramura default se execută când nicio constantă nu se potrivește.

Forma modernă folosește săgeata: case 1 -> .... Se execută doar ramura potrivită, fără break, iar o ramură poate avea mai multe valori: case 6, 7 ->. În forma veche, cu două puncte (case 1:), execuția continuă în ramurile următoare („fallthrough”) până la un break; uitarea lui break este o greșeală clasică.

default are și un al doilea înțeles în Java: în interfețe, default marchează o metodă cu implementare (vezi pagina despre interfețe). Când switch trebuie să producă o valoare, folosește switch expressions.

Exemple

Exemplul 1: Forma cu săgeată

Fiecare ramură execută doar codul ei. case 6, 7 grupează două valori.

public class Main {
    static void program(int zi) {
        switch (zi) {
            case 1, 2, 3, 4, 5 -> System.out.println(zi + ": zi lucrătoare, 9-17");
            case 6 -> System.out.println(zi + ": sâmbătă, 10-14");
            case 7 -> System.out.println(zi + ": duminică, închis");
            default -> System.out.println(zi + ": zi invalidă");
        }
    }

    public static void main(String[] args) {
        program(2);
        program(6);
        program(7);
        program(9);
    }
}

Rezultat

2: zi lucrătoare, 9-17
6: sâmbătă, 10-14
7: duminică, închis
9: zi invalidă

Exemplul 2: switch pe String

Din Java 7 se poate face switch pe texte; compararea folosește equals, deci contează literele mari și mici.

public class Main {
    static double pretBilet(String categorie) {
        double pret;
        switch (categorie) {
            case "elev", "student" -> pret = 10;
            case "pensionar" -> pret = 12.5;
            default -> pret = 25;
        }
        return pret;
    }

    public static void main(String[] args) {
        for (String c : new String[] {"student", "pensionar", "adult", "Elev"}) {
            System.out.println(c + ": " + pretBilet(c) + " lei");
        }
    }
}

Rezultat

student: 10.0 lei
pensionar: 12.5 lei
adult: 25.0 lei
Elev: 25.0 lei

Exemplul 3: Forma veche, cu break și fallthrough

Fără break, execuția „cade” în ramura următoare. Aici fallthrough-ul este intenționat (nivelurile se adună), de aceea metoda are @SuppressWarnings("fallthrough"); altfel javac -Xlint avertizează.

public class Main {
    @SuppressWarnings("fallthrough")
    static void beneficii(int nivel) {
        System.out.print("nivel " + nivel + ":");
        switch (nivel) {
            case 3:
                System.out.print(" lounge");
            case 2:
                System.out.print(" bagaj extra");
            case 1:
                System.out.print(" puncte");
                break;
            default:
                System.out.print(" nimic");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        beneficii(3);
        beneficii(1);
        beneficii(0);
    }
}

Rezultat

nivel 3: lounge bagaj extra puncte
nivel 1: puncte
nivel 0: nimic

Greșeli frecvente

  • Uitarea lui break în forma veche: se execută și ramurile următoare. Forma cu săgeată elimină problema.
  • switch pe String cu o valoare null aruncă NullPointerException (doar case null, din Java 21, o tratează).
  • Amestecarea în același switch a ramurilor cu : și cu ->: nu compilează.

Comenzi înrudite

  • switch expressions și yield: switch folosit ca expresie care produce o valoare; yield returnează valoarea dintr-o ramură cu bloc.
  • if și else: Execută un bloc doar dacă o condiție boolean este adevărată; else și else if tratează celelalte cazuri.
  • Pattern matching (instanceof și switch): Pattern matching testează tipul (și forma) unui obiect și îi extrage părțile într-un singur pas, în instanceof sau în switch.
  • enum: enum declară un tip cu un set fix de valori cu nume (zilele săptămânii, stările unei comenzi), verificat de compilator.
  • break și continue: break oprește bucla (sau switch-ul) curentă; continue sare peste restul pasului curent; cu etichete acționează asupra unei bucle exterioare.
  • Interfețe (interface, implements): O interfață (interface) descrie ce metode trebuie să aibă o clasă; clasa o promite cu implements și poate implementa mai multe interfețe.