Storia della questione:
La parola chiave instanceof è stata introdotta in Java per verificare se un oggetto appartiene a un determinato tipo o a uno dei suoi sottotipi. Questo meccanismo consente di definire il tipo di oggetto a runtime, cosa importante per lavorare con collezioni generiche, polimorfismo e casting dei tipi.
Problema:
Senza una corretta definizione del tipo di oggetto, possono verificarsi errori di ClassCastException o una gestione scorretta della logica nei rami del codice, se si esegue il casting dei tipi senza verifica. Un uso eccessivo di instanceof è spesso un segno di un design non riuscito.
Soluzione:
instanceof restituisce true se l'oggetto è un'istanza della classe specificata o di qualsiasi sua sottoclasse, oppure implementa l'interfaccia. In Java 16 è stato introdotto il pattern matching con casting automatico nel blocco if.
Esempio di codice:
Object obj = "Hello!"; if (obj instanceof String) { String s = (String) obj; // Il casting è sicuro System.out.println(s.length()); }
Con Java 16:
if (obj instanceof String s) { System.out.println(s.length()); // s è automaticamente castato a String }
Caratteristiche chiave:
null instanceof Type è sempre false)Cosa restituisce null instanceof SomeClass?
Sempre false. L'operatore garantisce che se l'oggetto è null, il risultato è false, escludendo NullPointerException.
È possibile utilizzare instanceof con parametri generici, ad esempio if (obj instanceof List<String>)?
No. A causa dell'erozione dei tipi (type erasure), non è possibile controllare i parametri generici a runtime. Il controllo viene sempre effettuato solo sul tipo raw (ad esempio, List).
Esempio di codice:
List<String> list = ...; if (list instanceof List<String>) { ... } // Errore di compilazione if (list instanceof List) { ... } // Consentito
L'uso di instanceof può indicare problemi nel design del codice?
Sì. L'uso costante di instanceof anziché applicare astrazioni o design patterns (ad esempio, il pattern Visitor) indica spesso una violazione dei principi della OOP, come l'apertura/chiusura.
Nel metodo esiste una lunga catena di if-else con controlli su tutti i possibili sottoclassi di una superclasse tramite instanceof, all'interno di ogni ramo ci sono casting di tipo e chiamate ai metodi appropriati.
Pro:
Contro:
Invece di if-else, è stato implementato il pattern Visitor: ogni sottoclasse ha un metodo che richiama il comportamento necessario, eliminando la necessità di instanceof.
Pro:
Contro: