Opérateur Java instanceof

1. Introduction

Dans ce rapide tutoriel, nous allons découvrir l' opérateur instanceof en Java.

2. Quelle est l' instance de l' opérateur?

instanceof est un opérateur binaire utilisé pour tester si un objet est d'un type donné. Le résultat de l'opération est vrai ou faux . Il est également connu sous le nom d'opérateur de comparaison de type car il compare l'instance avec le type.

Avant de lancer un objet inconnu, l' instance de vérification doit toujours être utilisée. Cela permet d'éviter ClassCastException au moment de l'exécution.

La syntaxe de base de l'opérateur instanceof est:

(object) instanceof (type)

Voyons un exemple de base pour l' opérateur instanceof . Tout d'abord, créons une classe Round :

public class Round { // implementation details }

Ensuite, créons une classe Ring qui étend Round :

public class Ring extends Round { // implementation details }

Nous pouvons utiliser instanceof pour vérifier si une instance de Ring est de type Round :

@Test public void givenWhenInstanceIsCorrect_thenReturnTrue() { Ring ring = new Ring(); Assert.assertTrue(ring instanceof Round); }

3. Comment fonctionne l' instance de l' opérateur?

L' opérateur instanceof fonctionne sur le principe de la relation is-a . Le concept de relation is-a est basé sur l'héritage de classe ou l'implémentation d'interface.

Pour illustrer cela, créons une interface Shape :

public interface Shape { // implementation details }

Créons également une classe Circle qui implémente l' interface Shape et étend également la classe Round :

public class Circle extends Round implements Shape { // implementation details }

Le résultat instanceof sera vrai si l'objet est une instance du type:

@Test public void givenWhenObjectIsInstanceOfType_thenReturnTrue() { Circle circle = new Circle(); Assert.assertTrue(circle instanceof Circle); }

Ce sera également vrai si l'objet est une instance d'une sous-classe du type:

@Test public void giveWhenInstanceIsOfSubtype_thenReturnTrue() { Circle circle = new Circle(); Assert.assertTrue(circle instanceof Round); }

Si le type est une interface, il retournera true si l'objet implémente l'interface:

@Test public void givenWhenTypeIsInterface_thenReturnTrue() { Circle circle = new Circle(); Assert.assertTrue(circle instanceof Shape); }

L' opérateur instanceof ne peut pas être utilisé s'il n'y a pas de relation entre l'objet comparé et le type avec lequel il est comparé.

Créons une nouvelle classe Triangle qui implémente Shape mais n'a aucune relation avec Circle :

public class Triangle implements Shape { // implementation details }

Maintenant, si nous utilisons instanceof pour vérifier si un Circle est une instance de Triangle :

@Test public void givenWhenComparingClassInDiffHierarchy_thenCompilationError() { Circle circle = new Circle(); Assert.assertFalse(circle instanceof Triangle); }

Nous obtiendrons une erreur de compilation car il n'y a pas de relation entre les classes Circle et Triangle :

java.lang.Error: Unresolved compilation problem: Incompatible conditional operand types Circle and Triangle

4. Utilisation de instanceof avec le type d' objet

En Java, chaque classe hérite implicitement de la classe Object . Par conséquent, l'utilisation de l' opérateur instanceof avec le type Object sera toujours évaluée à true :

@Test public void givenWhenTypeIsOfObjectType_thenReturnTrue() { Thread thread = new Thread(); Assert.assertTrue(thread instanceof Object); }

5. Utilisation de l' opérateur instanceof lorsqu'un objet est nul

Si nous utilisons l' opérateur instanceof sur n'importe quel objet qui est nul , il retourne false . De plus, aucune vérification nulle n'est nécessaire lors de l'utilisation d'un opérateur instanceof .

@Test public void givenWhenInstanceValueIsNull_thenReturnFalse() { Circle circle = null; Assert.assertFalse(circle instanceof Round); }

6. instanceof et génériques

Les tests d'instance et les transtypages dépendent de l'inspection des informations de type au moment de l'exécution. Par conséquent, nous ne pouvons pas utiliser instanceof avec des types génériques effacés .

Par exemple, si nous essayons de compiler l'extrait de code suivant:

public static  void sort(List collection) { if (collection instanceof List) { // sort strings differently } // omitted }

Ensuite, nous obtenons cette erreur de compilation:

error: illegal generic type for instanceof if (collection instanceof List) { ^

Techniquement parlant, nous ne sommes autorisés à utiliser instanceof qu'avec reifiedtypes en Java. Un type est réifié si ses informations de type sont présentes au moment de l'exécution.

Les types réifiés en Java sont les suivants:

  • Types primitifs comme int
  • Classes et interfaces non génériques comme String ou Random
  • Types génériques dans lesquels tous les types sont des caractères génériques illimités comme Set ou Map
  • Types bruts comme List ou HashMap
  • Tableaux d'autres types réifiable tels que String [], List [] ou Map []

Étant donné que les paramètres de type générique ne sont pas réifiés, nous ne pouvons pas non plus les utiliser:

public static  boolean isOfType(Object input) { return input instanceof T; // won't compile }

Cependant, il est possible de tester contre quelque chose comme List :

if (collection instanceof List) { // do something }

7. Conclusion

Dans ce tutoriel, nous avons découvert l' opérateur instanceof et comment l'utiliser. Les exemples de code complets sont disponibles à l'adresse over sur GitHub.