Qu'est-ce qu'une exception NullPointerException et comment la corriger?


210

Quelles sont les exceptions de pointeur nul ( java.lang.NullPointerException) et quelles en sont les causes?

Quelles méthodes / outils peuvent être utilisés pour déterminer la cause afin que vous empêchiez l'exception de provoquer l'arrêt prématuré du programme?

Réponses:


3767

Lorsque vous déclarez une variable de référence (c'est-à-dire un objet), vous créez vraiment un pointeur sur un objet. Considérez le code suivant où vous déclarez une variable de type primitif int:

int x;
x = 10;

Dans cet exemple, la variable xest un intet Java l'initialisera 0pour vous. Lorsque vous lui affectez la valeur de 10sur la deuxième ligne, votre valeur de 10est écrite dans l'emplacement mémoire désigné par x.

Mais, lorsque vous essayez de déclarer un type de référence , quelque chose de différent se produit. Prenez le code suivant:

Integer num;
num = new Integer(10);

La première ligne déclare une variable nommée num, mais elle ne contient pas encore de valeur primitive. Au lieu de cela, il contient un pointeur (car le type est Integerqui est un type de référence). Puisque vous n'avez pas encore dit sur quoi pointer, Java le définit null, ce qui signifie « Je ne pointe vers rien ».

Dans la deuxième ligne, le newmot-clé est utilisé pour instancier (ou créer) un objet de type Integeret la variable pointeur numest affectée à cet Integerobjet.

Cela NullPointerExceptionse produit lorsque vous déclarez une variable mais que vous n'avez pas créé d'objet et que vous l'assignez à la variable avant d'essayer d'utiliser le contenu de la variable (appelé déréférencement ). Vous pointez donc quelque chose qui n'existe pas réellement.

Le déréférencement se produit généralement lors de l'utilisation .pour accéder à une méthode ou un champ, ou [pour indexer un tableau.

Si vous essayez de déréférencer numAVANT de créer l'objet, vous obtenez un NullPointerException. Dans les cas les plus triviaux, le compilateur détectera le problème et vous fera savoir que " num may not have been initialized," mais parfois vous pouvez écrire du code qui ne crée pas directement l'objet.

Par exemple, vous pouvez avoir une méthode comme suit:

public void doSomething(SomeObject obj) {
   //do something to obj
}

Dans ce cas, vous ne créez pas l'objet obj, mais supposez plutôt qu'il a été créé avant l' doSomething()appel de la méthode. Remarque, il est possible d'appeler la méthode comme ceci:

doSomething(null);

Dans ce cas, objest null. Si la méthode est destinée à faire quelque chose à l'objet transmis, il convient de lancer le NullPointerExceptioncar c'est une erreur de programmeur et le programmeur aura besoin de ces informations à des fins de débogage. Veuillez inclure le nom de la variable objet dans le message d'exception, comme

Objects.requireNonNull(a, "a");

Alternativement, il peut y avoir des cas où le but de la méthode n'est pas uniquement d'opérer sur l'objet transmis, et donc un paramètre nul peut être acceptable. Dans ce cas, vous devrez vérifier un paramètre nul et vous comporter différemment. Vous devez également expliquer cela dans la documentation. Par exemple, doSomething()pourrait s'écrire:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj == null) {
       //do something
    } else {
       //do something else
    }
}

Enfin, comment localiser l'exception et la cause en utilisant Stack Trace

Quelles méthodes / outils peuvent être utilisés pour déterminer la cause afin que vous empêchiez l'exception de provoquer l'arrêt prématuré du programme?

Sonar avec findbugs peut détecter NPE. Le sonar peut-il intercepter dynamiquement les exceptions de pointeur nul causées par JVM


558
"La meilleure façon d'éviter ce type d'exception est de toujours vérifier la valeur null lorsque vous n'avez pas créé l'objet vous-même." Si l'appelant passe null, mais null n'est pas un argument valide pour la méthode, alors il est correct de renvoyer l'exception à l'appelant car c'est la faute de l'appelant. Ignorer silencieusement une entrée invalide et ne rien faire dans la méthode est un conseil extrêmement mauvais car il cache le problème.
Boann

104
J'ajouterais une remarque à propos de cet article expliquant que même les affectations aux primitives peuvent provoquer des NPE lors de l'utilisation de l'autoboxing: int a=bpeut lancer un NPE si b est un Integer. Il y a des cas où cela prête à confusion pour déboguer.
Simon Fischer

58
Est - il possible de capturer NPE jeté par une webapp à partir du navigateur Web comme il va montrer dans la source de la page de vue depuis le navigateur Web ..?
Sid

76
Oui, vérifiez si l'objet est égal à null avant d'appeler une méthode dessus ou essayez d'accéder à une variable qu'il pourrait avoir. Parfois, la structuration de votre code peut éviter une exception de pointeur nul. Par exemple, lors de la vérification d'une chaîne d'entrée avec une chaîne constante, vous devez commencer par la chaîne constante comme ici: if ("SomeString" .equals (inputString)) {} // même si inputString est null, aucune exception n'est levée. Il y a donc un tas de choses que vous pouvez faire pour essayer d'être en sécurité.
Rose

78
Une autre façon d'éviter les NullPointerExceptionproblèmes dans votre code est d'utiliser @Nullableet d' @NotNullannoter. La réponse suivante contient plus d'informations à ce sujet. Bien que cette réponse concerne spécifiquement l'IDE IntelliJ, elle est également applicable à d'autres outils comme l'est apparanet des commentaires. (BTW je ne suis pas autorisé à modifier cette réponse directement, peut-être que l'auteur peut l'ajouter?)
Arjan Mels

880

NullPointerExceptions sont des exceptions qui se produisent lorsque vous essayez d'utiliser une référence qui ne pointe vers aucun emplacement en mémoire (null) comme si elle faisait référence à un objet. Appeler une méthode sur une référence nulle ou essayer d'accéder à un champ d'une référence nulle déclenchera a NullPointerException. Ce sont les plus courants, mais d'autres moyens sont répertoriés sur la NullPointerExceptionpage javadoc.

L'exemple de code le plus rapide que je pourrais illustrer NullPointerExceptionserait probablement:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

Sur la première ligne à l'intérieur main, je définis explicitement la Objectréférence objégale à null. Cela signifie que j'ai une référence, mais qu'elle ne pointe vers aucun objet. Après cela, j'essaie de traiter la référence comme si elle pointe vers un objet en appelant une méthode dessus. Il en résulte un NullPointerExceptioncar il n'y a pas de code à exécuter à l'emplacement vers lequel pointe la référence.

(Ceci est une technicité, mais je pense qu'il convient de mentionner: Une référence qui pointe vers null n'est pas la même chose qu'un pointeur C qui pointe vers un emplacement de mémoire non valide. Un pointeur nul ne pointe littéralement nulle part , ce qui est subtilement différent de pointant vers un emplacement qui n'est pas valide.)


49
J'ai compris tout ce que vous y avez écrit, mais uniquement parce que je codais depuis un certain temps et que je sais ce qu'est un «pointeur» et une «référence» (et ce qu'est null, d'ailleurs). Quand j'essaie de plonger directement dans des explications comme ça, mes élèves me regardent crossey, parce qu'il n'y a pas assez de fond.
mmr

33
@mmr: Merci pour les commentaires, vous faites valoir un argument valable. Il est difficile sur Internet de vraiment juger où se trouve quelqu'un et à quel niveau il est sûr de commencer une explication. Je vais essayer de réviser cela à nouveau.
Bill the Lizard

22
Une manière plus courante d'obtenir une NullPointerException en pratique serait d'oublier d'initialiser explicitement une variable membre à autre chose nullqu'avant de l'utiliser, comme ceci . Avec les variables locales, le compilateur intercepterait cette erreur, mais dans ce cas, ce n'est pas le cas. Peut-être que cela apporterait un complément utile à votre réponse?
Ilmari Karonen

6
@EJP Je pense que vos points sont valides, j'ai donc mis à jour la réponse pour être plus claire et pour éviter de dire «points à null» là où elle l'a fait.
Steve Powell

5
@StevePowell J'ai indiqué il y a longtemps que je ne voulais pas que ma réponse change. Veuillez respecter l'intention de l'auteur original.
Bill the Lizard

697

Qu'est-ce qu'une NullPointerException?

Un bon point de départ est les JavaDocs . Ils ont ceci couvert:

Lancé lorsqu'une application tente d'utiliser null dans le cas où un objet est requis. Ceux-ci inclus:

  • Appel de la méthode d'instance d'un objet nul.
  • Accès ou modification du champ d'un objet nul.
  • Prendre la longueur de null comme s'il s'agissait d'un tableau.
  • Accéder ou modifier les emplacements de null comme s'il s'agissait d'un tableau.
  • Lancer null comme s'il s'agissait d'une valeur Throwable.

Les applications doivent lancer des instances de cette classe pour indiquer d'autres utilisations illégales de l'objet null.

Il est également possible que si vous essayez d'utiliser une référence nulle avec synchronized, cela lèvera également cette exception, par le JLS :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • Sinon, si la valeur de l'expression est nulle, a NullPointerExceptionest levé.

Comment je le répare?

Vous avez donc un NullPointerException. Comment le corrigez-vous? Prenons un exemple simple qui lance un NullPointerException:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

Identifier les valeurs nulles

La première étape consiste à identifier exactement les valeurs qui provoquent l'exception . Pour cela, nous devons effectuer un débogage. Il est important d'apprendre à lire une trace de pile . Cela vous montrera où l'exception a été levée:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

Ici, nous voyons que l'exception est levée sur la ligne 13 (dans la printStringméthode). Regardez la ligne et vérifiez quelles valeurs sont nulles en ajoutant des instructions de journalisation ou en utilisant un débogueur . Nous découvrons que sc'est nul, et appeler la lengthméthode dessus lève l'exception. Nous pouvons voir que le programme cesse de lever l'exception lorsqu'il s.length()est supprimé de la méthode.

Tracer l'origine de ces valeurs

Vérifiez ensuite d'où vient cette valeur. En suivant les appelants de la méthode, nous voyons que cela sest passé avec printString(name)dans la print()méthode et this.nameest nul.

Trace où ces valeurs doivent être définies

Où est this.nameplacé? Dans la setName(String)méthode. Avec un peu plus de débogage, nous pouvons voir que cette méthode n'est pas appelée du tout. Si la méthode a été appelée, vérifiez l' ordre dans lequel ces méthodes sont appelées et la méthode set n'est pas appelée après la méthode d'impression.

Cela suffit pour nous donner une solution: ajoutez un appel à printer.setName()avant d'appeler printer.print().

Autres correctifs

La variable peut avoir une valeur par défaut (et setNamepeut empêcher qu'elle soit définie sur null):

private String name = "";

La méthode printou printStringpeut vérifier la valeur null , par exemple:

printString((name == null) ? "" : name);

Ou vous pouvez concevoir la classe de sorte qu'elle name ait toujours une valeur non nulle :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

Voir également:

Je ne trouve toujours pas le problème

Si vous avez essayé de déboguer le problème et que vous n'avez toujours pas de solution, vous pouvez publier une question pour obtenir de l'aide, mais assurez-vous d'inclure ce que vous avez essayé jusqu'à présent. Au minimum, incluez le stacktrace dans la question et marquez les numéros de ligne importants dans le code. Essayez également de simplifier le code en premier (voir SSCCE ).


44
+1 Bon d'avoir un exemple qui comprend le passage par le stacktrace; il est important de montrer pourquoi sa lecture est importante pour le débogage de NPE. (et pourquoi nous recherchons presque toujours une trace de pile lorsque quelqu'un pose une question sur une erreur)
Dennis Meng

16
Vous avez mentionné le débogage ... Comment ça marche? Je fais des recherches sur le sujet depuis un certain temps maintenant, mais je ne trouve rien. Je suis sûr qu'un professeur incroyable comme vous peut me l'apprendre en une seconde! Merci beaucoup! :-)
Ruchir Baronia

15
@RuchirBaronia Un débogueur vous permet de parcourir un programme ligne par ligne pour voir quelles méthodes sont appelées et comment les variables sont modifiées. Les IDE devraient disposer de certains outils pour ce faire. Voir vogella.com/tutorials/EclipseDebugging/article.html par exemple.
fgb

15
@RuchirBaronia Vous définissez des points d'arrêt sur les méthodes autour de toutes les NullPointerExceptions comme indiqué dans le stacktrace, et vérifiez les valeurs des variables par rapport à ce que vous attendez qu'elles soient. Si vous savez qu'une variable est nulle alors qu'elle ne devrait pas l'être, vous pouvez définir des points d'arrêt autour de tout code qui modifie la valeur. Vous pouvez également utiliser des points d'arrêt conditionnels qui vous indiqueront quand une valeur change.
fgb

6
Définir les objets String sur une chaîne vide comme valeur par défaut est considéré comme une mauvaise pratique.
Tiny

502

Question: Qu'est-ce qui cause un NullPointerException(NPE)?

Comme vous devez le savoir, les types Java sont divisés en types primitifs ( boolean, int, etc.) et les types de référence . Les types de référence en Java vous permettent d'utiliser la valeur spéciale nullqui est la façon Java de dire "pas d'objet".

A NullPointerExceptionest lancé lors de l'exécution à chaque fois que votre programme tente d'utiliser un nullcomme s'il s'agissait d'une véritable référence. Par exemple, si vous écrivez ceci:

public class Test {
    public static void main(String[] args) {
        String foo = null;
        int length = foo.length();   // HERE
    }
}

l'instruction intitulée "ICI" va tenter d'exécuter la length()méthode sur une nullréférence, ce qui lancera a NullPointerException.

Il existe de nombreuses façons d'utiliser une nullvaleur qui entraînera un NullPointerException. En fait, les seules choses que vous pouvez faire avec un nullsans provoquer un NPE sont:

  • l'assigner à une variable de référence ou le lire à partir d'une variable de référence,
  • l'assigner à un élément du tableau ou le lire à partir d'un élément du tableau (à condition que la référence du tableau elle-même ne soit pas nulle!),
  • le passer comme paramètre ou le renvoyer comme résultat, ou
  • tester à l'aide des ==ou !=opérateurs, ou instanceof.

Question: Comment lire la trace de pile NPE?

Supposons que je compile et exécute le programme ci-dessus:

$ javac Test.java 
$ java Test
Exception in thread "main" java.lang.NullPointerException
    at Test.main(Test.java:4)
$

Premier constat: la compilation réussit! Le problème dans le programme n'est PAS une erreur de compilation. Il s'agit d'une erreur d' exécution . (Certains IDE peuvent avertir que votre programme lèvera toujours une exception ... mais pas le javaccompilateur standard .)

Deuxième constat: lorsque je lance le programme, il sort deux lignes de "gobbledy-gook". FAUX!! Ce n'est pas gobbledy-gook. Il s'agit d'une trace de pile ... et elle fournit des informations vitales qui vous aideront à retrouver l'erreur dans votre code si vous prenez le temps de la lire attentivement.

Voyons donc ce qu'il dit:

Exception in thread "main" java.lang.NullPointerException

La première ligne de la trace de pile vous indique un certain nombre de choses:

  • Il vous indique le nom du thread Java dans lequel l'exception a été levée. Pour un programme simple avec un thread (comme celui-ci), il sera "principal". Allons-nous en ...
  • Il vous indique le nom complet de l'exception qui a été levée; ie java.lang.NullPointerException.
  • Si l'exception a un message d'erreur associé, celui-ci sera affiché après le nom de l'exception. NullPointerExceptionest inhabituel à cet égard, car il contient rarement un message d'erreur.

La deuxième ligne est la plus importante pour diagnostiquer un NPE.

at Test.main(Test.java:4)

Cela nous indique un certain nombre de choses:

  • "at Test.main" dit que nous étions dans la mainméthode de la Testclasse.
  • "Test.java:4" donne le nom de fichier source de la classe, ET il nous indique que l'instruction où cela s'est produit est à la ligne 4 du fichier.

Si vous comptez les lignes dans le fichier ci-dessus, la ligne 4 est celle que j'ai étiquetée avec le commentaire "ICI".

Notez que dans un exemple plus compliqué, il y aura beaucoup de lignes dans la trace de pile NPE. Mais vous pouvez être sûr que la deuxième ligne (la première ligne "at") vous dira où le NPE a été lancé 1 .

En bref, la trace de la pile nous dira sans ambiguïté quelle instruction du programme a jeté le NPE.

1 - Pas tout à fait vrai. Il y a des choses appelées exceptions imbriquées ...

Question: Comment puis-je rechercher la cause de l'exception NPE dans mon code?

C'est la partie difficile. La réponse courte consiste à appliquer une inférence logique aux preuves fournies par la trace de pile, le code source et la documentation API appropriée.

Illustrons d'abord l'exemple simple (ci-dessus). Nous commençons par regarder la ligne que la trace de pile nous a indiqué est l'endroit où le NPE s'est produit:

int length = foo.length(); // HERE

Comment cela peut-il lancer un NPE?

En fait, il n'y a qu'une seule façon: cela ne peut arriver que si fooa la valeur null. Nous essayons ensuite d'exécuter la length()méthode nullet ... BANG!

Mais (je vous entends dire) et si le NPE était jeté à l'intérieur de l' length()appel de méthode?

Eh bien, si cela se produisait, la trace de la pile serait différente. La première ligne "at" dirait que l'exception a été levée dans une ligne de la java.lang.Stringclasse et la ligne 4 de Test.javaserait la deuxième ligne "at".

D'où cela nullvient-il? Dans ce cas, c'est évident, et il est évident ce que nous devons faire pour y remédier. (Attribuez une valeur non nulle à foo.)

OK, essayons donc un exemple un peu plus délicat. Cela nécessitera une déduction logique .

public class Test {

    private static String[] foo = new String[2];

    private static int test(String[] bar, int pos) {
        return bar[pos].length();
    }

    public static void main(String[] args) {
        int length = test(foo, 1);
    }
}

$ javac Test.java 
$ java Test
Exception in thread "main" java.lang.NullPointerException
    at Test.test(Test.java:6)
    at Test.main(Test.java:10)
$ 

Nous avons donc maintenant deux lignes "at". Le premier est pour cette ligne:

return args[pos].length();

et le second est pour cette ligne:

int length = test(foo, 1);

En regardant la première ligne, comment cela pourrait-il lancer un NPE? Il y a deux façons:

  • Si la valeur de barest nullalors bar[pos]lancera un NPE.
  • Si la valeur de bar[pos]est nullalors appelée length(), elle lancera un NPE.

Ensuite, nous devons déterminer lequel de ces scénarios explique ce qui se passe réellement. Nous commencerons par explorer le premier:

D'où barvient-il? Il s'agit d'un paramètre de l' testappel de méthode, et si nous regardons comment il a testété appelé, nous pouvons voir qu'il provient de la foovariable statique. De plus, nous pouvons voir clairement que nous avons initialisé fooà une valeur non nulle. Cela suffit pour écarter provisoirement cette explication. (En théorie, quelque chose d'autre pourrait changer foo en null... mais cela ne se produit pas ici.)

Et notre deuxième scénario? Eh bien, nous pouvons voir que posc'est le cas 1, ce qui signifie que cela foo[1]doit être null. Est-ce possible?

En effet, ça l'est! Et voilà le problème. Lorsque nous initialisons comme ceci:

private static String[] foo = new String[2];

nous allouons un String[]avec deux éléments qui sont initialisés ànull . Après cela, nous n'avons pas changé le contenu de foo... ce foo[1]sera toujours le cas null.


426

C'est comme si vous essayez d'accéder à un objet qui l'est null. Considérez l'exemple ci-dessous:

TypeA objA;

Pour l'instant, vous venez de déclarer cet objet mais pas initialisé ni instancié . Et chaque fois que vous essayez d'accéder à une propriété ou une méthode, elle lance NullPointerExceptionce qui a du sens.

Voir également cet exemple ci-dessous:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown

1
Si nous donnons System.out.println (a.length ()); // NullPointerException sera levée, pour ignorer cela, nous pouvons gérer avec try catch block. merci
Vijaya Varma Lanke

360

Une exception de pointeur null est levée lorsqu'une application tente d'utiliser null dans le cas où un objet est requis. Ceux-ci inclus:

  1. Appel de la méthode d'instance d'un nullobjet.
  2. Accéder ou modifier le champ d'un nullobjet.
  3. Prendre la longueur de nullcomme s'il s'agissait d'un tableau.
  4. Accéder ou modifier les emplacements nullcomme s'il s'agissait d'une baie.
  5. Lancer nullcomme s'il s'agissait d'une valeur Throwable.

Les applications doivent lancer des instances de cette classe pour indiquer d'autres utilisations illégales de l' nullobjet.

Référence: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html


12
Restez simple, j'aime cette réponse, ajoutez ceci si vous le jugez correct - Accès à l'attribut non initialisé d'un objet
Emiliano

5
@Emiliano - accéder simplement à un attribut initialisé ne provoque pas de NPE. C'est ce que vous >> faites << avec la valeur d'attribut non initialisée qui provoque le NPE.
Stephen C

1
Si vous voulez plus de cas: 1) en utilisant un nullcomme cible d'un synchronizedbloc, 2) en utilisant un nullcomme cible d'un switch, et unboxing null.
Stephen C

334

Un nullpointeur est celui qui ne pointe nulle part. Lorsque vous déréférencer un pointeur p, vous dites "donnez-moi les données à l'emplacement stocké dans" p ". Quand pest un nullpointeur, l'emplacement stocké dans pest nowhere, vous dites" donnez-moi les données à l'emplacement "nulle part" ". De toute évidence, il ne peut pas faire cela, il lance donc a null pointer exception.

En général, c'est parce que quelque chose n'a pas été correctement initialisé.


2
Sommes-nous en train de créer une base de données? -> NULLs'écrit comme nullen java. Et c'est une chose sensible à la casse.
bvdb

3
"Un pointeur NULL est celui qui ne pointe nulle part", je ne suis pas d'accord. Les pointeurs nuls ne pointent vers nulle part, ils pointent vers des valeurs nulles.
TheRealChx101

2
@ TheRealChx101 Un pointeur nul et un pointeur vers une valeur nulle sont des choses différentes - un pointeur nul ne pointe pas vers une valeur nulle. Supposons que vous ayez un pointeur vers un pointeur: le pointeur A pointe vers le pointeur B et le pointeur B est nul. Dans ce cas, le pointeur A pointe vers une valeur nulle et le pointeur B est un pointeur nul.
MrZebra

322

De nombreuses explications sont déjà présentes pour expliquer comment cela se produit et comment y remédier, mais vous devez également suivre les meilleures pratiques pour éviter NullPointerExceptiontout.

Voir aussi: Une bonne liste de bonnes pratiques

J'ajouterais, très important, de bien utiliser le finalmodificateur. Utilisation du modificateur "final" chaque fois qu'il est applicable en Java

Résumé:

  1. Utilisez le finalmodificateur pour appliquer une bonne initialisation.
  2. Évitez de renvoyer null dans les méthodes, par exemple en renvoyant des collections vides le cas échéant.
  3. Utilisez des annotations @NotNullet@Nullable
  4. Échouez rapidement et utilisez des assertions pour éviter la propagation d'objets nuls à travers toute l'application alors qu'ils ne devraient pas être nuls.
  5. Utilisez d'abord égal à un objet connu: if("knownObject".equals(unknownObject)
  6. Préférez valueOf()plus toString().
  7. Utilisez des StringUtilsméthodes sûres nulles StringUtils.isEmpty(null).
  8. Utilisez Java 8 facultatif comme valeur de retour dans les méthodes, la classe facultative fournit une solution pour représenter des valeurs facultatives au lieu de références nulles.

4
Dans les projets j2ee, l'exception Nullpointer est très courante.Certains cas, les variables de référence ont des valeurs nulles.Vous devez donc vérifier l'initialisation de la variable correctement.Et pendant l'instruction conditionnelle, vous devez toujours vérifier que l'indicateur ou la référence contient null ou pas comme: - if (flag! = 0) {votre code qui utilise le drapeau}
Amaresh Pattanayak

14
Il convient de mentionner que certains IDE (par exemple Eclipse) offrent des analyses de nullité automatiques basées sur des annotations personnalisables (par exemple, @Nullablecomme indiqué ci-dessus) et mettent en garde contre les erreurs potentielles. Il est également possible d'inférer et de générer de telles annotations (par exemple, IntelliJ peut le faire) sur la base de la structure de code existante.
Jan Chimiak

4
La première chose à faire est avant d'utiliser un objet nullable, vous devez vérifier s'il est nul, en utilisant if (obj==null). S'il est nul, vous devez également écrire du code pour gérer cela également.
Lakmal Vithanage

4
OMI, il est préférable d'éviter de renvoyer des objets nuls dans les méthodes lorsque cela est possible et d'utiliser des annotations lorsque les paramètres d'entrée nuls ne sont pas autorisés afin, par contrat, de réduire la quantité de ´si (obj == null) ´ dans le code et d'améliorer la lisibilité du code.
LG

4
Lisez ceci ... avant d'accepter ces "meilleures pratiques" comme vérité: satisfice.com/blog/archives/27
Stephen C

317

En Java, tout (à l'exception des types primitifs) se présente sous la forme d'une classe.

Si vous souhaitez utiliser n'importe quel objet, vous avez deux phases:

  1. Déclarer
  2. Initialisation

Exemple:

  • Déclaration: Object object;
  • Initialisation: object = new Object();

Idem pour le concept de baie:

  • Déclaration: Item item[] = new Item[5];
  • Initialisation: item[0] = new Item();

Si vous ne donnez pas la section d'initialisation, le NullPointerExceptionproblème survient.


3
Une exception NullPointerException se produit souvent lors de l'appel de la méthode d'une instance. Par exemple, si vous déclarez une référence mais ne la fait pointer vers aucune instance, NullPointerException se produit lorsque vous appelez sa méthode. tels que: YourClass ref = null; // ou ref = anotherRef; // mais anotherRef n'a pointé aucune instance ref.someMethod (); // il lèvera NullPointerException. Corrigez-le généralement de cette manière: Avant d'appeler la méthode, déterminez si la référence est nulle. comme: if (yourRef! = null) {yourRef.someMethod (); }
sunhang

2
Ou utilisez la capture d'exceptions: par exemple: try {yourRef.someMethod (); } catch (NullPointerException e) {// TODO}
sunhang


316

Une exception de pointeur nul est un indicateur que vous utilisez un objet sans l'initialiser.

Par exemple, ci-dessous se trouve une classe d'étudiants qui l'utilisera dans notre code.

public class Student {

    private int id;

    public int getId() {
        return this.id;
    }

    public setId(int newId) {
        this.id = newId;
    }
}

Le code ci-dessous vous donne une exception de pointeur nul.

public class School {

    Student student;

    public School() {
        try {
            student.getId();
        }
        catch(Exception e) {
            System.out.println("Null pointer exception");
        }
    }
}

Parce que vous utilisez student, mais vous avez oublié de l'initialiser comme dans le bon code ci-dessous:

public class School {

    Student student;

    public School() {
        try {
            student = new Student();
            student.setId(12);
            student.getId();
        }
        catch(Exception e) {
            System.out.println("Null pointer exception");
        }
    }
}

7
Bien que ce soit un bel exemple, puis-je demander ce qu'il ajoute à la question qui n'est pas déjà couverte par toutes les autres réponses?
Mysticial

13
Il est tout simplement inapproprié d'utiliser le mot «non initialisé» ici. L'exemple que vous avez montré est en fait "initialisé" et il est initialisé avec null. Pour les variables non initialisées, le compilateur se plaindra à vous.
Adrian Shum

2
Un NPE peut être un indicateur que vous utilisez un champ non initialisé. Cela peut être un indicateur que vous faites d'autres choses. Une simplification excessive à une seule cause comme celle-ci n'aide pas quelqu'un à résoudre les problèmes NPE ... si la cause réelle n'est pas celle-ci.
Stephen C

309

En Java, toutes les variables que vous déclarez sont en fait des "références" aux objets (ou primitives) et non aux objets eux-mêmes.

Lorsque vous essayez d'exécuter une méthode d'objet, la référence demande à l'objet vivant d'exécuter cette méthode. Mais si la référence fait référence à NULL (rien, zéro, vide, nada), il n'y a aucun moyen d'exécuter la méthode. Ensuite, le runtime vous le fait savoir en lançant une NullPointerException.

Votre référence "pointe" vers null, donc "Null -> Pointer".

L'objet vit dans l'espace mémoire de la machine virtuelle et le seul moyen d'y accéder est d'utiliser des thisréférences. Prenez cet exemple:

public class Some {
    private int id;
    public int getId(){
        return this.id;
    }
    public setId( int newId ) {
        this.id = newId;
    }
}

Et à un autre endroit de votre code:

Some reference = new Some();    // Point to a new object of type Some()
Some otherReference = null;     // Initiallly this points to NULL

reference.setId( 1 );           // Execute setId method, now private var id is 1

System.out.println( reference.getId() ); // Prints 1 to the console

otherReference = reference      // Now they both point to the only object.

reference = null;               // "reference" now point to null.

// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );

// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...

C'est une chose importante à savoir - quand il n'y a plus de références à un objet (dans l'exemple ci-dessus quand referenceet les otherReferencedeux pointent vers null) alors l'objet est "inaccessible". Il n'y a aucun moyen de travailler avec lui, donc cet objet est prêt à être récupéré, et à un moment donné, la machine virtuelle libérera la mémoire utilisée par cet objet et en allouera une autre.


281

Une autre occurrence de a NullPointerExceptionse produit lorsque l'on déclare un tableau d'objets, puis essaie immédiatement de déréférencer des éléments à l'intérieur de celui-ci.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Ce NPE particulier peut être évité si l'ordre de comparaison est inversé; à savoir, utiliser .equalssur un objet non nul garanti.

Tous les éléments à l'intérieur d'un tableau sont initialisés à leur valeur initiale commune ; pour tout type de tableau d'objets, cela signifie que tous les éléments le sont null.

Vous devez initialiser les éléments du tableau avant d'y accéder ou de les déréférencer.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

L'opération sur un objet non initialisé au niveau de l'instance (pas au niveau de la classe) conduira à NullPointerException. l'opération doit être spécifique à l'instance. si l'opération est au niveau de la classe, disant appeler une méthode statique sur un objet non initialisé, elle ne lèvera pas d'exception NullPointerException. Même les objets de classe wrapper primitifs lèvent NullPointerException.
Shailendra Singh

1. NullPointerException est une RuntimeException, cela signifie qu'il apparaîtra lorsque votre programme est en cours d'exécution, vous ne le ferez pas au moment de la compilation.! :(, mais la plupart des IDE vous aident à découvrir cela. 2. Minimisez l'utilisation du mot clé 'null' dans les instructions d'affectation. :) URL de référence:
tomj0101

@ tomj0101 Je ne comprends pas très bien pourquoi vous avez fait ce commentaire ... Mais pour votre deuxième point, un modèle avant Optionaldevait retourner null. Le mot-clé est très bien. Savoir se prémunir contre cela est essentiel. Cela en offre une occurrence courante et des moyens de l'atténuer.
Makoto

NullPointerException est une exception d' exécution qui n'est pas recommandée pour l'attraper, mais à la place l'éviter.
Shomu

2
@Shomu: À quel moment est-ce que je suggère même de le capturer?
Makoto
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.