Class.isInstance vs Class.isAssignableFrom

1. Introduction

Dans ce rapide didacticiel, nous allons examiner la différence entre Class.isInstance et Class.isAssignableFrom . Nous apprendrons comment utiliser chaque méthode et quelles sont les différences entre elles.

2. Configuration

Configurons une interface et quelques classes à utiliser pendant que nous explorons les fonctionnalités Class.isInstance et Class.isAssignableFrom .

Tout d'abord, définissons une interface:

public interface Shape { }

Ensuite, définissons une classe qui implémente Shape :

public class Triangle implements Shape { }

Maintenant, nous allons créer une classe qui étend Triangle :

public class IsoscelesTriangle extends Triangle { }

3. Class.isInstance

La méthode isInstance sur la classe Class est équivalente à l' opérateur instanceof . La méthode isInstance a été introduite dans Java 1.1 car elle peut être utilisée de manière dynamique. Cette méthode retournera true si l'argument n'est pas nul et peut être converti avec succès en type référence sans déclencher une ClassCastException .

Voyons comment nous pouvons utiliser la méthode isInstance avec l'interface et les classes que nous avons définies:

@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)); }

Comme on peut le voir, le côté droit peut être équivalent ou plus spécifique que le côté gauche . Fournir null à la méthode isInstance retourne false .

4. Class.isAssignableFrom

La méthode Class.isAssignableFrom retournera true si la classe sur le côté gauche de l'instruction est identique ou est une superclasse ou une super-interface du paramètre Class fourni .

Utilisons nos classes avec la méthode 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())); }

Comme avec l' exemple isInstance , nous pouvons clairement voir que le côté droit doit être le même ou plus spécifique que le côté gauche. Nous pouvons également voir que nous ne sommes jamais en mesure d'attribuer notre interface Shape .

5. Les différences

Maintenant que nous avons présenté quelques exemples détaillés, passons en revue certaines des différences:

  1. Pour utiliser isInstance , nous devons savoir quelle est l'une des classes au moment de la compilation.
  2. Seul isAssignableFrom peut être utilisé avec des primitives. Il faut noter que si nous utilisons des primitives, la méthode ne retournera vrai si la classe objet et classe paramètres sont exactement de la même classe .
  3. La méthode isAssignableFrom lèvera une NullPointerException si l'objet utilisé de chaque côté de l'expression est nul . Si vous fournissez une valeur null à la méthode isInstance , elle retournera false .
  4. Nous devrions penser à isInstance comme répondant à la question de savoir si l'objet fourni est le type auquel nous le comparons (soit directement, soit via l'interface ou l'héritage). Nous pouvons penser que isAssignableFrom répond à la question de savoir si nous pouvons définir la classe de paramètres comme classe d'objets. En d'autres termes, Triangle triangle = new IsoscelesTriange () sera- t-il compilé?

6. Conclusion

Dans ce court didacticiel, nous avons examiné les méthodes Class.isInstance et Class.isAssignableFrom et avons exploré leur utilisation et leurs différences.

Comme toujours, l'exemple de code de ce didacticiel se trouve à l'adresse over sur GitHub.