Class.isInstance contro Class.isAssignableFrom

1. Introduzione

In questo rapido tutorial, daremo un'occhiata alla differenza tra Class.isInstance e Class.isAssignableFrom . Impareremo come utilizzare ogni metodo e quali sono le differenze tra di loro.

2. Configurazione

Configuriamo un'interfaccia e un paio di classi da utilizzare mentre esploriamo le funzionalità Class.isInstance e Class.isAssignableFrom .

Per prima cosa, definiamo un'interfaccia:

public interface Shape { }

Successivamente, definiamo una classe che implementa Shape :

public class Triangle implements Shape { }

Ora creeremo una classe che estende Triangle :

public class IsoscelesTriangle extends Triangle { }

3. Class.isInstance

Il metodo isInstance sulla classe Class è equivalente all'operatore instanceof . Il metodo isInstance è stato introdotto in Java 1.1 perché può essere utilizzato dinamicamente. Questo metodo restituirà true se l'argomento non è null e può essere eseguito correttamente il cast al tipo di riferimento senza generare un'eccezione ClassCastException .

Diamo un'occhiata a come possiamo usare il metodo isInstance con l'interfaccia e le classi che abbiamo definito:

@Test public void whenUsingIsInstanceProperly_desiredResultsHappen() { Shape shape = new Triangle(); Triangle triangle = new Triangle(); IsoscelesTriangle isoscelesTriangle = new IsoscelesTriangle(); Triangle isoscelesTriangle2 = new IsoscelesTriangle(); Shape nonspecificShape = null; assertTrue(Shape.class.isInstance(shape)); assertTrue(Shape.class.isInstance(triangle)); assertTrue(Shape.class.isInstance(isoscelesTriangle)); assertTrue(Shape.class.isInstance(isoscelesTriangle2)); assertFalse(Shape.class.isInstance(nonspecificShape)); assertTrue(Triangle.class.isInstance(shape)); assertTrue(Triangle.class.isInstance(triangle)); assertTrue(Triangle.class.isInstance(isoscelesTriangle)); assertTrue(Triangle.class.isInstance(isoscelesTriangle2)); assertFalse(IsoscelesTriangle.class.isInstance(shape)); assertFalse(IsoscelesTriangle.class.isInstance(triangle)); assertTrue(IsoscelesTriangle.class.isInstance(isoscelesTriangle)); assertTrue(IsoscelesTriangle.class.isInstance(isoscelesTriangle2)); }

Come possiamo vedere, il lato destro può essere equivalente o più specifico del lato sinistro . Fornire null al metodo isInstance restituisce false .

4. Class.isAssignableFrom

Il metodo Class.isAssignableFrom restituirà true se la classe sul lato sinistro dell'istruzione è uguale o è una superclasse o superinterfaccia del parametro Class fornito .

Usiamo le nostre classi con il metodo isAssignableFrom :

@Test public void whenUsingIsAssignableFromProperly_desiredResultsHappen() { Shape shape = new Triangle(); Triangle triangle = new Triangle(); IsoscelesTriangle isoscelesTriangle = new IsoscelesTriangle(); Triangle isoscelesTriangle2 = new IsoscelesTriangle(); assertFalse(shape.getClass().isAssignableFrom(Shape.class)); assertTrue(shape.getClass().isAssignableFrom(shape.getClass())); assertTrue(shape.getClass().isAssignableFrom(triangle.getClass())); assertTrue(shape.getClass().isAssignableFrom(isoscelesTriangle.getClass())); assertTrue(shape.getClass().isAssignableFrom(isoscelesTriangle2.getClass())); assertFalse(triangle.getClass().isAssignableFrom(Shape.class)); assertTrue(triangle.getClass().isAssignableFrom(shape.getClass())); assertTrue(triangle.getClass().isAssignableFrom(triangle.getClass())); assertTrue(triangle.getClass().isAssignableFrom(isoscelesTriangle.getClass())); assertTrue(triangle.getClass().isAssignableFrom(isoscelesTriangle2.getClass())); assertFalse(isoscelesTriangle.getClass().isAssignableFrom(Shape.class)); assertFalse(isoscelesTriangle.getClass().isAssignableFrom(shape.getClass())); assertFalse(isoscelesTriangle.getClass().isAssignableFrom(triangle.getClass())); assertTrue(isoscelesTriangle.getClass().isAssignableFrom(isoscelesTriangle.getClass())); assertTrue(isoscelesTriangle.getClass().isAssignableFrom(isoscelesTriangle2.getClass())); assertFalse(isoscelesTriangle2.getClass().isAssignableFrom(Shape.class)); assertFalse(isoscelesTriangle2.getClass().isAssignableFrom(shape.getClass())); assertFalse(isoscelesTriangle2.getClass().isAssignableFrom(triangle.getClass())); assertTrue(isoscelesTriangle2.getClass().isAssignableFrom(isoscelesTriangle.getClass())); assertTrue(isoscelesTriangle2.getClass().isAssignableFrom(isoscelesTriangle2.getClass())); }

Come con l' esempio isInstance , possiamo vedere chiaramente che il lato destro deve essere lo stesso o più specifico del lato sinistro. Possiamo anche vedere che non siamo mai in grado di assegnare la nostra interfaccia Shape .

5. Le differenze

Ora che abbiamo presentato un paio di esempi dettagliati, esaminiamo alcune delle differenze:

  1. Per poter usare isInstance , dobbiamo sapere qual è una delle classi in fase di compilazione.
  2. Solo isAssignableFrom può essere utilizzato con le primitive. Dobbiamo notare che , se stiamo usando primitive, il metodo sarà solo tornare vero se la classe dell'oggetto e Classe parametri sono esattamente la stessa classe .
  3. Il metodo isAssignableFrom genererà un'eccezione NullPointerException se l'oggetto utilizzato su entrambi i lati dell'espressione è null . Se fornisci un valore null al metodo isInstance , restituirà false .
  4. Dovremmo pensare a isInstance come una risposta alla domanda se l'oggetto fornito è il tipo con cui lo stiamo confrontando (direttamente o tramite interfaccia o ereditarietà). Possiamo pensare a isAssignableFrom come una risposta alla domanda se possiamo definire la classe di parametri come classe di oggetti. In altre parole, Triangle triangle = new IsoscelesTriange () verrà compilato?

6. Conclusione

In questo breve tutorial, abbiamo esaminato entrambi i metodi Class.isInstance e Class.isAssignableFrom ed esplorato il loro utilizzo e come differiscono.

Come sempre, il codice di esempio per questo tutorial può essere trovato su GitHub.