Ce face switch expressions și yield
Din Java 14, switch poate fi o expresie: produce o valoare pe care o pui într-o variabilă, o returnezi sau o transmiți unei metode. Fiecare ramură case ... -> valoare; dă rezultatul, iar întregul switch se termină cu ; când e folosit într-o atribuire.
Un switch expression trebuie să fie exhaustiv: să acopere toate valorile posibile. Pentru numere și texte asta înseamnă default; pentru un enum sau o ierarhie sealed ajunge să tratezi toate cazurile, iar compilatorul verifică.
Când o ramură are nevoie de mai multe instrucțiuni, scrii un bloc între acolade și dai valoarea cu yield. yield este un cuvânt cheie contextual: are sens doar în switch expressions și se poate folosi și în forma cu două puncte (case 1: yield "unu";).
Exemple
Exemplul 1: Numele zilei
Rezultatul switch-ului este pus direct în variabila nume.
public class Main {
public static void main(String[] args) {
for (int zi = 1; zi <= 8; zi += 3) {
String nume = switch (zi) {
case 1 -> "luni";
case 2 -> "marți";
case 3 -> "miercuri";
case 4 -> "joi";
case 5 -> "vineri";
case 6, 7 -> "weekend";
default -> "necunoscut";
};
System.out.println(zi + " = " + nume);
}
}
}
Rezultat
1 = luni
4 = joi
7 = weekend
Exemplul 2: yield într-un bloc
Ramura pentru „transfer” calculează un comision în mai mulți pași și dă rezultatul cu yield.
public class Main {
static double comision(String operatie, double suma) {
return switch (operatie) {
case "depunere" -> 0;
case "retragere" -> 2.5;
case "transfer" -> {
double procent = suma * 0.005;
double minim = 1.0;
yield Math.max(procent, minim);
}
default -> throw new IllegalArgumentException("operație necunoscută: " + operatie);
};
}
public static void main(String[] args) {
System.out.println(comision("depunere", 500));
System.out.println(comision("retragere", 500));
System.out.println(comision("transfer", 1000));
System.out.println(comision("transfer", 50));
try {
comision("împrumut", 100);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}
Rezultat
0.0
2.5
5.0
1.0
operație necunoscută: împrumut
Exemplul 3: Exhaustiv pe enum, fără default
Toate cele patru anotimpuri sunt tratate, deci default nu e necesar. Dacă adaugi un anotimp nou în enum, codul nu mai compilează până nu tratezi și cazul nou.
public class Main {
enum Anotimp { PRIMAVARA, VARA, TOAMNA, IARNA }
static String activitate(Anotimp a) {
return switch (a) {
case PRIMAVARA -> "plantăm flori";
case VARA -> "mergem la mare";
case TOAMNA -> "culegem struguri";
case IARNA -> "facem oameni de zăpadă";
};
}
public static void main(String[] args) {
for (Anotimp a : Anotimp.values()) {
System.out.println(a + ": " + activitate(a));
}
}
}
Rezultat
PRIMAVARA: plantăm flori
VARA: mergem la mare
TOAMNA: culegem struguri
IARNA: facem oameni de zăpadă
Greșeli frecvente
- Lipsa lui
defaultla un switch expression peintsauString:the switch expression does not cover all possible input values. - Folosirea lui
returnîn loc deyieldîntr-un bloc al unui switch expression: nu compilează. - Uitarea lui
;după acolada finală când switch-ul este într-o atribuire.
Comenzi înrudite
switch, case și default: Alege ce cod se execută comparând o valoare cu mai multe constante case; default tratează orice altă valoare.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.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.sealed, permits și non-sealed: O clasă sau interfață sealed își alege explicit subtipurile (permits); fiecare subtip este final, sealed sau non-sealed.