Ce face instanceof
x instanceof Tip dă true dacă obiectul din x este de tipul Tip sau al unei subclase / implementări a lui. Pentru null rezultatul este mereu false, deci instanceof nu aruncă niciodată NullPointerException.
Înainte de Java 16, după verificare urma o conversie explicită: if (o instanceof String) { String s = (String) o; ... }. Forma cu pattern face ambele dintr-o dată: if (o instanceof String s). Variabila s există doar acolo unde compilatorul știe sigur că testul a reușit.
Când ai multe ramuri instanceof la rând, un switch cu pattern-uri este de obicei mai clar. Iar dacă te trezești testând tipul ca să alegi comportamentul, poate e mai bine o metodă rescrisă în fiecare subclasă (polimorfism).
Ce returnează
boolean: true dacă obiectul nu este null și este de tipul cerut.
Exemple
Exemplul 1: Verificare de tip, cu subclase și null
Un Integer este și Number, și Object. null nu este instanță a niciunui tip.
public class Main {
public static void main(String[] args) {
Object[] valori = {"Iași", 42, 3.14, null};
for (Object v : valori) {
System.out.println(v + ": String? " + (v instanceof String)
+ ", Number? " + (v instanceof Number)
+ ", Object? " + (v instanceof Object));
}
}
}
Rezultat
Iași: String? true, Number? false, Object? true
42: String? false, Number? true, Object? true
3.14: String? false, Number? true, Object? true
null: String? false, Number? false, Object? false
Exemplul 2: Forma veche și forma cu pattern
Ambele metode fac același lucru. Varianta nouă nu mai repetă tipul și nu are conversie manuală. Variabila pattern poate fi folosită chiar în aceeași condiție, după &&.
public class Main {
static String vechi(Object o) {
if (o instanceof String) {
String s = (String) o;
return "text de " + s.length() + " caractere";
}
return "altceva";
}
static String nou(Object o) {
if (o instanceof String s && !s.isBlank()) {
return "text de " + s.length() + " caractere";
}
if (o instanceof Integer n && n > 0) {
return "număr pozitiv, dublul = " + (n * 2);
}
return "altceva";
}
public static void main(String[] args) {
System.out.println(vechi("Suceava"));
System.out.println(nou("Suceava"));
System.out.println(nou(" "));
System.out.println(nou(21));
System.out.println(nou(-3));
}
}
Rezultat
text de 7 caractere
text de 7 caractere
altceva
număr pozitiv, dublul = 42
altceva
Exemplul 3: Negație și ieșire timpurie
După if (!(o instanceof Elev e)) return ...;, compilatorul știe că mai jos o este sigur un Elev, deci e poate fi folosită în restul metodei.
record Elev(String nume, double medie) { }
public class Main {
static String diploma(Object o) {
if (!(o instanceof Elev e)) {
return "nu este elev: " + o;
}
return e.medie() >= 9.5 ? e.nume() + " primește premiul I" : e.nume() + " primește diplomă de participare";
}
public static void main(String[] args) {
System.out.println(diploma(new Elev("Daria", 9.8)));
System.out.println(diploma(new Elev("Tudor", 8.4)));
System.out.println(diploma("Bianca"));
}
}
Rezultat
Daria primește premiul I
Tudor primește diplomă de participare
nu este elev: Bianca
Greșeli frecvente
- Faci conversia fără verificare:
(String) oaruncăClassCastExceptiondacăoeste, de fapt, unInteger. - Folosești variabila pattern unde testul poate să fi eșuat, de exemplu după
||:cannot find symbol. - Testezi un tip care nu are cum să se potrivească (
String s; s instanceof Integer):incompatible types: String cannot be converted to Integer.
Comenzi înrudite
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.Record patterns: Un record pattern verifică tipul unui record și îi desface direct componentele în variabile, inclusiv pentru records imbricate.Polimorfism: Polimorfismul înseamnă că același apel (f.arie()) execută metoda clasei reale a obiectului, chiar dacă variabila are tipul superclasei.sealed, permits și non-sealed: O clasă sau interfață sealed își alege explicit subtipurile (permits); fiecare subtip este final, sealed sau non-sealed.