[Résolu][Java] Mystérieuse NullPointerException

J’ai un problème pour le moins curieux avec un de mes programmes en Java.
J’ai une classe qui contient une ArrayList et un entier. L’ArrayList contient des couples caractère - valeur booléenne. L’ArrayList représente un mot des ces couples. Le but de la méthode qui balance l’exception est de faire une réduction : si on a (a;faux)(b;vrai) et (a;faux)(b;faux), la réduction doit donner un nouveau motif (a;faux). Pour plus de simplicité on note aussi ça a’b et a’b’ se réduisent en a’.

L’algorithme est le suivant :
Entrée : m1 et m2 deux motifs
On suppose qu’on s’est déjà assuré que les deux motifs ont la même taille
Pour chaque couple dans m1, on regarde si on en trouve un dans m2 où le caractère est le même mais de valeur booléenne opposée. Si c’est le cas, on réduit en éliminant ce couple.
Si on ne trouve rien, on renvoie un truc vide.

Bref, je teste la méthode avec les motifs ab’cd et d’b’ca ; ce qui est supposé renvoyer ab’c. Et là j’ai la NullPointerException :

/** * Effectue une réduction entre le motif courant et le motif m. * Il est IMPERATIF que les deux motifs aient une distance de 1. * L'effectif est la somme des effectifs des deux motifs précédents. * * @param m Le motif avec lequel on va faire la réduction * @return Un motif réduit à partir du motif courant et de m : par exemple si this = ab'c et m = abc, cela renverra ac. Si malgrès tout les motifs n'ont pas pu être réduit, la méthode renvoie un motif null. */ motif reduction(motif m) { motif reduit = new motif(this.effectif + m.effectif); // Des entiers... for(int i = 0; i < m.motif.size(); i++) { System.out.println("i="+i); if(m.quasiContient(this.motif.get(i))) { // On copie le contenu du motif dans p : for(int j = 0; j < this.motif.size(); j++) { System.out.println("j="+j+"\n"+this.motif.get(j)); // Là ça affiche reduit.motif.add(this.motif.get(j)); // Là ça foire ! } // On vire la lettre repérée reduit.motif.remove(i); } else { reduit.motif = null; } } return reduit; }

Et voilà le contenu de la sortie :

23 : ab'cd // C'est l'entier contenu dans la structure de donnée 24 : d'b'ca // C'est l'entier contenu dans la structure de donnée Les deux motifs ne sont pas égaux... Leur distance est de 1 Raté ! i=0 i=1 i=2 i=3 j=0 a Exception in thread "main" java.lang.NullPointerException at motif.reduction(motif.java:160) at motif.main(motif.java:249)

Et là, je dois dire que je ne comprend pas comment ça se fait que la même méthode dans un System.out.println() fonctionne et que dans un add la ligne juste après, sur le même objet, il me jette cette exception…
Le pire est que la méthode marchait sans problèmes dans une version antérieure où la seule différence était que le motif de sortie n’était jamais mis à null même si on ne trouvait rien à réduire…

Difficile de juger sans avoir le corp de chaque méthode (en regardant ton code, je me dis que l’expression peut être levée dans ton get() autant que dans le remove() après le for)…

A mon avis le problème ne vient pas de ton this.motif.get(j) mais plutot de reduit.motif.add(). Sachant que tu mets l’objet concerné (reduit.motif) à null à un moment, il y a des chances que ton algo soit buggé. De plus, dans ton Sop(), tu ne fait appel à cet objet, toute la différence est peut-être là.

Autres explication, ta méthode get() fait un traitement qui met certains attributs (voir l’objet lui-même) à null, ce qui provoque cette exception au 2ème appel. Enfin, si tu as des opérations asynchrones, il est possible qu’un attribut ou l’objet lui-même soti mis à null entre le 1er et le 2ème appel de get().

Ha, ça y est, ça fonctionne. Merci de m’avoir signalé cette mise à null du motif, qui n’était pas au bon endroit. Je viens de voir que tel que décrit dans le code que je file, ça ne pouvait que foirer puisque si la méthode ne trouvait pas de lettre différent au booléen prêt, elle mettait le motif résultat à null, ce qui n’était pas le but recherché du tout, mais était inévitable.

A la place, j’ai mis au début un booléen à faux, si la méthode trouve quelque chose à réduire, elle le met à vrai. A la fin, on regarde le booléen, s’il est toujours à faut, on met un motif null, sinon, on laisse et on renvoie le bousin et ça fonctionne.

Merci bien :stuck_out_tongue: !

Juste pour faire mon chieur, attention de respecter les conventions Java, les noms de classe commencent par une majuscule parce qu’entre le motif m, reduit.motif, this.motif, ce n’est pas très clair…

Ca faisait quasiment un an que j’avais pas fait de Java, alors les convention de nommage, je les ai un peu oubliées. Mais je veux bien que tu me les rappelles pour mes futurs projets en Java que je ferais cet été pour m’occuper un peu :P.

Voilà :

http://java.sun.com/docs/codeconv/