1. Introduzione
In questo breve tutorial, impareremo a conoscere l' operatore instanceof in Java.
2. Qual è l' istanza dell'operatore?
instanceof è un operatore binario utilizzato per verificare se un oggetto è di un determinato tipo. Il risultato dell'operazione è vero o falso . È anche noto come operatore di confronto del tipo perché confronta l'istanza con il tipo.
Prima di lanciare un oggetto sconosciuto, è sempre necessario utilizzare l' istanza di controllo. In questo modo è possibile evitare ClassCastException in fase di esecuzione.
La sintassi di base dell'operatore instanceof è:
(object) instanceof (type)
Vediamo un esempio di base per l' operatore instanceof . Per prima cosa, creiamo un round di classe :
public class Round { // implementation details }
Successivamente, creiamo un anello di classe che si estende Round :
public class Ring extends Round { // implementation details }
Possiamo usare instanceof per verificare se un'istanza di Ring è di tipo Round :
@Test public void givenWhenInstanceIsCorrect_thenReturnTrue() { Ring ring = new Ring(); Assert.assertTrue(ring instanceof Round); }
3. Come funziona l' istanza dell'operatore?
L' operatore instanceof funziona sul principio della relazione is-a . Il concetto di relazione è-un si basa sull'ereditarietà della classe o sull'implementazione dell'interfaccia.
Per dimostrarlo, creiamo un'interfaccia Shape :
public interface Shape { // implementation details }
Creiamo anche una classe Circle che implementa l' interfaccia Shape ed estende anche la classe Round :
public class Circle extends Round implements Shape { // implementation details }
L' istanza del risultato sarà vera se l'oggetto è un'istanza del tipo:
@Test public void givenWhenObjectIsInstanceOfType_thenReturnTrue() { Circle circle = new Circle(); Assert.assertTrue(circle instanceof Circle); }
Sarà anche vero se l'oggetto è un'istanza di una sottoclasse del tipo:
@Test public void giveWhenInstanceIsOfSubtype_thenReturnTrue() { Circle circle = new Circle(); Assert.assertTrue(circle instanceof Round); }
Se il tipo è un'interfaccia, restituirà true se l'oggetto implementa l'interfaccia:
@Test public void givenWhenTypeIsInterface_thenReturnTrue() { Circle circle = new Circle(); Assert.assertTrue(circle instanceof Shape); }
L' operatore instanceof non può essere utilizzato se non esiste alcuna relazione tra l'oggetto che viene confrontato e il tipo con cui viene confrontato.
Creiamo una nuova classe Triangle che implementa Shape ma non ha alcuna relazione con Circle :
public class Triangle implements Shape { // implementation details }
Ora, se usiamo instanceof per verificare se un cerchio è un'istanza di triangolo :
@Test public void givenWhenComparingClassInDiffHierarchy_thenCompilationError() { Circle circle = new Circle(); Assert.assertFalse(circle instanceof Triangle); }
Otterremo un errore di compilazione perché non esiste alcuna relazione tra le classi Circle e Triangle :
java.lang.Error: Unresolved compilation problem: Incompatible conditional operand types Circle and Triangle
4. Utilizzo di instanceof con il tipo di oggetto
In Java, ogni classe eredita implicitamente dalla classe Object . Pertanto, l'utilizzo dell'operatore instanceof con il tipo Object restituirà sempre true :
@Test public void givenWhenTypeIsOfObjectType_thenReturnTrue() { Thread thread = new Thread(); Assert.assertTrue(thread instanceof Object); }
5. Utilizzo dell'operatore instanceof quando un oggetto è nullo
Se utilizziamo l' operatore instanceof su qualsiasi oggetto null , restituisce false . Inoltre, non è necessario alcun controllo null quando si utilizza un operatore instanceof .
@Test public void givenWhenInstanceValueIsNull_thenReturnFalse() { Circle circle = null; Assert.assertFalse(circle instanceof Round); }
6. instanceof e Generics
I test e i cast delle istanze dipendono dall'ispezione delle informazioni sul tipo in fase di esecuzione. Pertanto, non possiamo usare instanceof insieme a tipi generici cancellati .
Ad esempio, se proviamo a compilare il seguente frammento:
public static void sort(List collection) { if (collection instanceof List) { // sort strings differently } // omitted }
Quindi otteniamo questo errore di compilazione:
error: illegal generic type for instanceof if (collection instanceof List) { ^
Tecnicamente parlando, ci è permesso usare solo instanceof insieme a reifiedtipi in Java. Un tipo viene reificato se le relative informazioni sul tipo sono presenti in fase di esecuzione.
I tipi reificati in Java sono i seguenti:
- Tipi primitivi come int
- Classi e interfacce non generiche come String o Random
- Tipi generici in cui tutti i tipi sono caratteri jolly illimitati come Set o Map
- Tipi grezzi come List o HashMap
- Matrici di altri tipi modificabili come String [], List [] o Map []
Poiché i parametri di tipo generico non sono reificati, non possiamo usarli neanche:
public static boolean isOfType(Object input) { return input instanceof T; // won't compile }
Tuttavia, è possibile testare qualcosa come List :
if (collection instanceof List) { // do something }
7. Conclusione
In questo tutorial, abbiamo imparato a conoscere l' operatore instanceof e come usarlo. Gli esempi di codice completi sono disponibili su GitHub.