instanceof en Java : faut-il vérifier la valeur null ? Analyse sous le capot

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

instanceof en Java : faut-il vérifier la valeur null ? Plongeons sous le capot de la JVM

\n\n

Chaque développeur Java se retrouve tôt ou tard face à un dilemme : faut-il écrire avant l'appel à instanceof la lourde construction if (obj != null && obj instanceof SomeClass) ou peut-on se contenter d'un simple instanceof ? Cette question, qui a recueilli des milliers de vues sur Stack Overflow, reste d'actualité. Penchons-nous une fois pour toutes sur le fonctionnement de cet opérateur « sous le capot » et déterminons si la double vérification relève de la paranoïa ou d'une bonne pratique.

\n\n

Si vous programmez en Java et souhaitez écrire un code propre, sûr et efficace, cet article est pour vous. Nous ne nous contenterons pas de répondre par « oui » ou « non », mais nous montrerons le bytecode, explorerons la spécification de la JVM et présenterons des exemples concrets.

\n\n

Réponse courte : votre intuition est correcte

\n\n

Allons droit au but : la vérification de null avant instanceof n'est pas nécessaire. L'opérateur instanceof en Java est conçu de telle sorte que si l'opérande gauche est null, il retourne toujours false. Aucun NullPointerException ne sera levé. Cela est spécifié dans la spécification du langage Java (§15.20.2) et confirmé par le comportement de toutes les implémentations existantes de la JVM.

\n\n

Mais ne nous arrêtons pas à cette simple affirmation. Pourquoi cela a-t-il été fait ainsi ? Comment cela fonctionne-t-il au niveau des instructions machine ? Et quand la double vérification peut-elle être justifiée ?

\n\n

Comment instanceof fonctionne sous le capot : un regard sur le bytecode

\n\n

Considérons une classe et une méthode simples :

\n\n
public class InstanceofTest {\n    public static boolean check(Object obj) {\n        return obj instanceof String;\n    }\n}
\n\n

Compilons et examinons le bytecode (commande javap -c InstanceofTest) :

\n\n
public static boolean check(java.lang.Object);\n    Code:\n       0: aload_0\n       1: instanceof #7                  // class java/lang/String\n       4: ireturn
\n\n

Nous voyons seulement trois instructions :

\n
    \n
  • aload_0 — charge la référence de l'objet depuis la variable locale 0 (notre paramètre obj)
  • \n
  • instanceof #7 — effectue la vérification de type
  • \n
  • ireturn — retourne le résultat (0 ou 1)
  • \n
\n\n

Remarquez : il n'y a aucune instruction pour vérifier la valeur null ! L'instruction JVM instanceof gère elle-même ce cas. Si la pile d'opérandes contient null (une valeur de référence spéciale pointant vers nulle part), l'instruction retourne simplement 0 (false).

\n\n

Que se passe-t-il au niveau de la JVM ?

\n\n

À l'intérieur de la machine virtuelle Java, l'instruction instanceof effectue les étapes suivantes :

\n
    \n
  1. Vérification de null : Si la référence est null, retourne immédiatement false. Cela est fait au tout début, avant toute opération mémoire.
  2. \n
  3. Obtention du pointeur de classe : Si l'objet n'est pas null, la JVM extrait de son en-tête le pointeur vers la classe (dans HotSpot, cela fait partie de la structure mark word et klass pointer).
  4. \n
  5. Vérification de compatibilité : La JVM vérifie si la classe de l'objet est la même classe, une sous-classe ou une implémentation d'interface que celle spécifiée dans l'opérande droit. Pour cela, un algorithme rapide avec mise en cache des résultats (inline caching) et une recherche dans la chaîne d'héritage sont utilisés.
  6. \n
\n\n

Ainsi, la vérification de null n'est pas une « particularité du langage », mais une propriété fondamentale de l'implémentation de la JVM, rendant le code plus sûr et plus concis.

\n\n

Exemples de code : vérifions en pratique

\n\n

Assurons-nous que cela fonctionne en écrivant un test simple :

\n\n
public class NullInstanceofDemo {\n    public static void main(String[] args) {\n        String text = "Hello";\n        String nullString = null;\n\n        System.out.println("text instanceof String: " + (text instanceof String));         // true\                

Blogs

Book Recommendations