Operatore instanceof in Java
Verifica il tipo a runtime di un oggetto con instanceof e usa il pattern matching per instanceof in Java.
instanceof pone una domanda a runtime: "questo riferimento è effettivamente un T (o un sottotipo di T)?" La risposta è un boolean, e la moderna forma con pattern matching può anche legare il valore a una variabile tipizzata in un unico passaggio, eliminando la necessità di un cast separato.
È lo strumento da utilizzare quando si ha un riferimento polimorfico e si deve determinare quale tipo concreto sia davvero — tipicamente all'interno di equals, quando si attraversa una struttura dati eterogenea, o quando si lavora con gerarchie sealed.
La forma base
La sintassi classica è expression instanceof Type:
Object o = "hello";
if (o instanceof String) {
String s = (String) o;
System.out.println(s.length());
}Il controllo restituisce true se o fa riferimento a una String o a un suo sottotipo, e false se o è null o punta a un tipo diverso. null instanceof Anything è sempre false — una garanzia piccola ma utile.
Pattern matching per instanceof
A partire da Java 16, instanceof accetta un type pattern che dichiara una variabile legata al tipo ristretto nella stessa espressione:
if (o instanceof String s) {
System.out.println(s.length()); // no cast needed
}Se il controllo ha successo, s è in scope ed è già tipizzata come String. Se fallisce, s non è in scope. Il cast è sparito, la ridondanza è sparita, e non è possibile eseguire accidentalmente il cast di qualcosa che il controllo ha rifiutato.
Scope della variabile legata
La variabile legata è in scope ovunque il compilatore possa dimostrare che il controllo ha avuto successo. Questo include il ramo if, ma si propaga anche attraverso && e nella negazione dell'if:
if (o instanceof String s && s.length() > 3) { ... } // s is in scope after && — also a String
if (!(o instanceof String s)) return;
System.out.println(s.length()); // s is in scope after the early returnIl secondo pattern è particolarmente utile per il codice in stile guard-clause — si restringe il tipo, si esce se non corrisponde, e si usa liberamente il nome legato più in basso.
Il lato opposto è ||: il binding non si propaga attraverso di esso, perché il lato destro viene eseguito proprio quando il controllo è fallito. o instanceof String s || s.length() > 0 non compila — s non è in scope a destra di ||.
Restrizioni sul tipo target
Il compilatore rifiuta i controlli che può dimostrare essere impossibili. "hello" instanceof Integer non compilerà nemmeno, perché String e Integer non sono correlati. Questo intercetta refusi ed errori di refactoring a tempo di compilazione anziché a runtime.
Rifiuta anche gli upcast che non possono fallire: Object o = ...; if (o instanceof Object) {} viene segnalato come ridondante.
In switch
La stessa macchina di pattern matching è disponibile in switch, dove brilla davvero su gerarchie sealed:
String describe(Object o) {
return switch (o) {
case Integer i -> "int " + i;
case String s -> "str of length " + s.length();
case int[] a -> "array of " + a.length;
case null -> "nothing";
default -> "something else";
};
}Con un tipo sealed come selettore, è possibile eliminare il default e il compilatore richiederà un caso per ogni sottotipo consentito — abbinalo alle sealed classes per ottenere un'analisi dei casi esaustiva.
Quando usarlo — e quando non farlo
Usa instanceof quando il tipo è genuinamente sconosciuto e la risposta cambia il comportamento: implementando equals, elaborando gerarchie sealed a unione etichettata, attraversando nodi AST. Non usarlo come sostituto del polimorfismo corretto — una catena di if (x instanceof A) ... else if (x instanceof B) ... su una gerarchia aperta è solitamente un segnale che un metodo virtuale sul tipo farebbe il lavoro meglio.
Un esempio pratico
Cosa c'è dopo
instanceof è uno dei vari metodi a cui ogni oggetto Java risponde. Il prossimo capitolo allarga la prospettiva per esaminare l'intero insieme — java.lang.Object, la classe radice che ogni tipo estende silenziosamente, e i metodi che si ereditano da essa che lo si voglia o meno. Continua con la classe Object di Java.