Menu

NullPointerException en Java : causes et comment la corriger

Ce que signifie vraiment une NullPointerException en Java, les façons courantes de la déclencher, comment lire le message et les modèles qui la préviennent.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

L'erreur la plus courante en Java

Une NullPointerException (tout le monde l'appelle une NPE) survient lorsque vous essayez d'utiliser une référence qui ne pointe vers rien -null- comme si elle pointait vers un véritable objet. Les variables Java de type objet contiennent soit un objet, soit null, la valeur signifiant « aucun objet ici ». Dès l'instant où vous demandez à null de faire quelque chose - appeler une méthode, lire l'un de ses champs, l'indexer - il n'y a rien sur quoi agir, donc la JVM lève une exception.

Contrairement à try-catch, auquel vous recourez à la page précédente pour gérer les échecs attendus, une NPE est presque toujours un simple bug. Le but de cette page n'est pas de les attraper, mais de comprendre pourquoi elles surviennent et d'écrire du code qui ne les produit pas.

Il n'y a aucun String sur lequel length() puisse s'exécuter, donc le programme s'arrête avec une NullPointerException.

Lire le message

Depuis Java 14, le message vous indique exactement ce qui était null - on appelle cela la Helpful NullPointerException (NPE utile). Lisez-le avant de changer quoi que ce soit :

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "name" is null
	at Main.main(Main.java:4)

Deux éléments comptent. Cannot invoke "String.length()" est l'opération qui a échoué, et because "name" is null désigne le coupable. La ligne at Main.main(Main.java:4) est la trace de pile qui pointe vers la ligne exacte. La correction n'est donc pas « entourer la ligne 4 d'un try » - c'est « comprendre pourquoi name vaut null à la ligne 4 ». Presque toujours, le bug se trouve quelque part en amont, là où la valeur aurait dû être affectée et ne l'a pas été.

Les façons de la déclencher

Les NPE proviennent d'une poignée d'opérations, toutes des variations de « toucher à null » :

Les recherches dans les maps sont une source classique : get renvoie null lorsque la clé est absente, et la NPE surgit souvent quelques lignes plus loin, lorsque vous utilisez enfin cette valeur. Le déballage est le cas sournois : affecter un Integer valant null à un int lève une exception, car il n'y a aucun nombre à copier.

Se protéger avec une vérification de null

La défense la plus simple est un if qui confirme qu'une référence n'est pas nulle avant de l'utiliser :

Lorsque vous comparez une variable à un String constant, placez la constante en premier - "yes".equals(answer) plutôt que answer.equals("yes"). Si answer vaut null, la première forme renvoie tranquillement false, tandis que la seconde lève une exception.

Échouer vite avec Objects.requireNonNull

Disséminer des vérifications de null partout devient bruyant. Lorsqu'une valeur ne devrait jamais être null - comme un argument de constructeur - validez-la à la frontière avec Objects.requireNonNull. Elle lève immédiatement, avec un message clair, à l'endroit où la mauvaise valeur arrive plutôt que bien plus tard, au fond de votre code :

Cette habitude d'« échouer vite » transforme une NPE floue 200 lignes plus loin en une plainte précise à la source. Attraper l'exception ici ne sert qu'à afficher le message - dans du vrai code, vous la laisseriez remonter pour que le bug soit corrigé.

Éviter les null dès le départ

La meilleure NPE est celle qui ne peut jamais survenir parce qu'il n'y a aucun null à atteindre. Quelques habitudes font beaucoup :

  • Renvoyez une collection ou une chaîne vide, jamais null. Collections.emptyList() et "" peuvent être parcourus et appelés en toute sécurité.
  • Utilisez getOrDefault sur les maps pour qu'une recherche infructueuse produise une vraie valeur au lieu de null.
  • Initialisez les champs au moment de les déclarer plutôt que de les laisser à null jusqu'à « plus tard ».

Lorsqu'une valeur est réellement optionnelle - une recherche qui peut légitimement ne rien trouver - Java propose Optional, un conteneur qui force l'appelant à gérer le cas « absent » au lieu de renvoyer silencieusement un null. C'est le concept connexe à lire ensuite si vous voulez éliminer entièrement ces manques de la conception de vos API.

Pour conclure

Une NullPointerException, c'est Java qui vous dit que vous avez utilisé une référence contenant null comme si elle contenait un objet. La correction consiste rarement à l'attraper - il s'agit de lire le message utile, de remonter jusqu'à l'endroit où la valeur aurait dû être définie, et soit de garantir qu'elle n'est pas nulle, soit de protéger l'endroit où vous l'utilisez. Appuyez-vous sur Objects.requireNonNull pour échouer vite aux frontières, préférez des valeurs vides et getOrDefault à null, et recourez à Optional lorsque l'absence est un résultat réel et attendu. Maîtrisez cet état d'esprit, et l'erreur la plus courante en Java deviendra l'une des plus rares dans votre propre code.

Questions fréquentes

Qu'est-ce qui provoque une NullPointerException en Java ?

Cela arrive lorsque vous utilisez une référence pointant vers null comme si elle pointait vers un véritable objet - par exemple en appelant une méthode (name.length()), en lisant un champ, en accédant à un élément de tableau ou en déballant un Integer valant null. La variable ne contient aucun objet, il n'y a donc rien sur quoi agir et la JVM lève une NullPointerException.

Comment corriger une NullPointerException en Java ?

Lisez le message - depuis Java 14, il indique exactement ce qui était null (par ex. "Cannot invoke "String.length()" because "name" is null"). Cherchez ensuite pourquoi cette variable est null : une initialisation manquante, une méthode ayant renvoyé null, ou une recherche dans une map qui n'a rien trouvé. Corrigez la source pour que la valeur ne soit jamais null, ou protégez l'utilisation avec une vérification de null, Objects.requireNonNull ou Optional.

Vaut-il mieux vérifier null ou attraper une NullPointerException ?

Vérifiez null. Une NullPointerException signale un bug dans votre logique, pas une condition attendue, vous devez donc la prévenir plutôt que l'attraper. L'attraper masque l'endroit où se trouve le vrai problème. Réservez try/catch aux situations réellement exceptionnelles, comme les erreurs d'E/S.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER