Ce face Pattern matching (instanceof și switch)
Un pattern (tipar) combină o verificare și o declarație: Integer i înseamnă „dacă valoarea este un Integer, pune-o în i”. Tiparele apar în instanceof (Java 16) și în case (Java 21), unde un switch poate primi orice obiect, nu doar numere, texte și enum-uri.
Un case poate avea o condiție suplimentară cu when: case Integer i when i > 100. Ramurile se verifică în ordine, deci cazurile particulare trebuie puse înaintea celor generale; compilatorul refuză un caz care nu mai poate fi atins (this case label is dominated by a preceding case label).
Un switch cu tipare trebuie să fie complet: fie are default, fie acoperă toate subtipurile unui tip sealed. Fără case null, un switch pe null aruncă NullPointerException. Tiparele de record (record patterns) duc ideea mai departe și desfac și componentele.
Exemple
Exemplul 1: switch pe tipuri, cu when și case null
Fiecare valoare ajunge pe prima ramură care i se potrivește. case null tratează explicit null, iar default prinde restul.
import java.util.Arrays;
import java.util.List;
public class Main {
static String descrie(Object o) {
return switch (o) {
case null -> "valoare lipsă";
case Integer i when i < 0 -> "întreg negativ: " + i;
case Integer i -> "întreg: " + i;
case Double d -> String.format("real: %.2f", d);
case String s when s.isBlank() -> "text gol";
case String s -> "text: \"" + s + "\" (" + s.length() + " car.)";
case List<?> l -> "listă cu " + l.size() + " elemente";
default -> "alt tip: " + o.getClass().getSimpleName();
};
}
public static void main(String[] args) {
List<Object> valori = Arrays.asList(7, -3, 2.5, "Brașov", " ", List.of(1, 2, 3), null, 'x');
for (Object v : valori) {
System.out.println(descrie(v));
}
}
}
Rezultat
întreg: 7
întreg negativ: -3
real: 2.50
text: "Brașov" (6 car.)
text gol
listă cu 3 elemente
valoare lipsă
alt tip: Character
Exemplul 2: Ierarhie sigilată: switch complet fără default
Eveniment este sealed, deci compilatorul știe că switch-ul acoperă toate cazurile. Condiția when separă plățile mari de cele obișnuite.
sealed interface Eveniment { }
record Autentificare(String utilizator) implements Eveniment { }
record Plata(String utilizator, double suma) implements Eveniment { }
record Deconectare(String utilizator, int minute) implements Eveniment { }
public class Main {
static String jurnal(Eveniment e) {
return switch (e) {
case Autentificare a -> a.utilizator() + " s-a conectat";
case Plata p when p.suma() >= 1000 -> "ATENȚIE: " + p.utilizator() + " a plătit " + p.suma() + " lei";
case Plata p -> p.utilizator() + " a plătit " + p.suma() + " lei";
case Deconectare d -> d.utilizator() + " a plecat după " + d.minute() + " min";
};
}
public static void main(String[] args) {
Eveniment[] evenimente = {
new Autentificare("ana"),
new Plata("ana", 89.9),
new Plata("ana", 2400),
new Deconectare("ana", 17),
};
for (Eveniment e : evenimente) {
System.out.println(jurnal(e));
}
}
}
Rezultat
ana s-a conectat
ana a plătit 89.9 lei
ATENȚIE: ana a plătit 2400.0 lei
ana a plecat după 17 min
Greșeli frecvente
- Pui cazul general înaintea celui particular (
case Integer iînainte decase Integer i when i < 0):this case label is dominated by a preceding case label. - Uiți
defaultcând tipul nu este sigilat:the switch expression does not cover all possible input values. - Trimiți
nullîntr-un switch fărăcase null: se aruncăNullPointerException.
Comenzi înrudite
instanceof: instanceof verifică dacă un obiect este de un anumit tip; în forma nouă declară și o variabilă deja convertită la acel tip.Record patterns: Un record pattern verifică tipul unui record și îi desface direct componentele în variabile, inclusiv pentru records imbricate.sealed, permits și non-sealed: O clasă sau interfață sealed își alege explicit subtipurile (permits); fiecare subtip este final, sealed sau non-sealed.switch expressions și yield: switch folosit ca expresie care produce o valoare; yield returnează valoarea dintr-o ramură cu bloc.switch, case și default: Alege ce cod se execută comparând o valoare cu mai multe constante case; default tratează orice altă valoare.