Exception in thread "main" java.lang.Nul

Résolu/Fermé
seljazou Messages postés 175 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 25 décembre 2009 - 9 déc. 2009 à 01:57
seljazou Messages postés 175 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 25 décembre 2009 - 13 déc. 2009 à 17:54
Bonjour,


voici une partie de mon programme
------------------------------------------------------------------------------------------


public class codeVoiture {

public static void main(String[] args){

voiture Toyota = new voiture ();

Toyota.chevaux = 6;
Toyota.nombreDePlaces[0] = 2;
Toyota.nombreDePlaces[1] = 8;

Toyota.prix(Toyota.chevaux, Toyota.nombreDePlaces);

voiture Renault = new voiture ();
Renault.chevaux = 3;
Renault.nombreDePlaces[0] = 1;
Renault.nombreDePlaces[1] = 2;
Renault.prix(Renault.chevaux, Renault.nombreDePlaces);

}
}

-------------------------------------------------------------------
Le résultat est : Exception in thread "main" java.lang.NullPointerException

---------------------------------------------------------------------


j'ai ajouté des constructeurs

public voiture ();

mais on m reponde que cette expression is indefined.


j'essaie de garder mon sang froid!! où est le problème??

merci de votre attention.

4 réponses

Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013 660
9 déc. 2009 à 02:12
me revoilà ^^

Tout d'abord le moins important pour ton souci :

Toyota.prix(Toyota.chevaux, Toyota.nombreDePlaces);
Renault.prix(Renault.chevaux, Renault.nombreDePlaces);

tu n'as pas besoin de passer les données d'un objet en paramètre à une méthode de la classe. Elle peut directement accéder aux variables de l'objet en question. c'est d'ailleurs tout l'intéret de la programmation objet : tu ne devrais pas manipuler les données directement mais seulement via les méthodes public et mettre les variables en private.

Bon c'est un programme pour essayer donc ce n'est pas grave le truc des variables private, ceci dit il ne faut quand meme pas passer les variables de l'objet en paramètre.


De plus, met plutôt le nom de ta classe voiture avec une majuscule : Voiture, comme c'est un nom de classe et pour tout de suite prendre de bonnes habitudes ;) .


Ensuite, concernant ton problème :
normalement ça aurait du fonctionner. Il y a un constructeur par défaut. Et pour l'erreur que tu obtiens :

public voiture ();

là tu déclares juste un prototype de méthode.
Il faut que tu donnes une définition, une implémentation :

public voiture () {
}


même si le corps est vide. D'où l'erreur "undefined".


Peux-tu donner le code de ta classe ? (avec les balises code si possible)
1
seljazou Messages postés 175 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 25 décembre 2009 1
9 déc. 2009 à 02:17
Quand tu as dit :
" tu n'as pas besoin de passer les données d'un objet en paramètre à une méthode de la classe. Elle peut directement accéder aux variables de l'objet en question "

est ce que ça veut dire qu'il aurait suffit que je fasse
Toyota.prix();
Renault.prix();

ou bien

Toyota.prix(chevaux, nombreDePlaces);
Renault.prix(chevaux, nombreDePlaces);

?


sinon voici le code ( j'avoue c un peu embarassant :p mais c mon tout premier programme, avant je ne faisais que lire les cours )

---------------------------------------------------------------

public class voiture {
int chevaux;
int[] nombreDePlaces;
public void prix(int chevaux, int[] nombreDePlaces){
if ( chevaux > 5 & nombreDePlaces[1] > 3) {

System.out.println(" votre voiture coûte un million d'euros");
}
else {
System.out.println("mais c une vrais ordure ce que vous voulez acheter");
}
}
}

-----------------------------------------------------------------------------------

merci beaucoup :)
0
Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013 660 > seljazou Messages postés 175 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 25 décembre 2009
9 déc. 2009 à 02:31
PS :


sinon voici le code ( j'avoue c un peu embarassant :p mais c mon tout premier programme, avant je ne faisais que lire les cours )


Tu apprendras mille fois plus en lisant le cours ET en faisant des petits programmes pour appliquer ce dont il parle, c'est essentiel pour comprendre, continue comme ça ;)
0
seljazou Messages postés 175 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 25 décembre 2009 1 > Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013
9 déc. 2009 à 02:48
oui :p c plus efficace en pratiquant :) j'admets
0
Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013 660
9 déc. 2009 à 02:27
c'est bien

Toyota.prix();
Renault.prix();

que je voulais dire.

Et la méthode saura bien que les variables chevaux et nombreDePlaces dans le corps de ta méthode sont celles de l'objet en question (pour être plus précis le compilateur interprètera alors "chevaux" et "nombreDePlaces" dans le code de ta méthode comme this.chevaux et this.nombreDePlace . this est un pointeur qui est "passé en paramètre à la méthode implicitement" qui pointe vers l'objet depuis lequel elle a été appelée.


Le problème de nullpointerexception vient, je pense, de ceci :int[] nombreDePlaces;

C'est un tableau c'est une sorte d'objet, donc il pointe par défaut à NULL.

En gros tu as déclaré une variable tableau mais tu ne l'as pas crée.

Bon là je peux me tromper, mais je pense qu'il faut simplement mettre dans le constructeur ceci :
nombreDePlaces = new int[2];
1
seljazou Messages postés 175 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 25 décembre 2009 1
9 déc. 2009 à 02:54
j'ai réesayé, mais ça ne marche toujours pas .
même quand je mets la méthode ( pas le prototype ;) ... du constructeur, ça ne marche pas, on me dit : illegal start of expression.

puis aussi avec le main ça ne s'arrange pas, il est toujours indefined.

et j'ai essayé de refaire le code avec le 'this', mais je trébuche encore.

mais je commence à voir l'utilité du 'this' :)

merci :)


0
Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013 660
9 déc. 2009 à 19:51
en général on ne se sert du this que pour enlever l'ambiguïté (il y a d'autres utilités avec l'héritage mais laissons ça de côté) :

Ex: dans la classe Voiture tu pourrais avoir une méthode :
// sert à changer le nombre de chevaux de l'objet courant, sans utiliser directement 
// la variable chevaux comme dans objet.chevaux = 30;
//on utilisera donc plutot : objet.changerNombreDeChevaux(30)
void changerNbrChevaux(int chevaux) {
  this.chevaux = chevaux;
}


le premier this.chevaux fait référence à la variable chevaux de l'objet, tandis que le deuxième chevaux fait référence au nom du paramètre de la méthode (variable locale qui, si on ne précise rien, "masque" la variable de l'objet.)

même quand je mets la méthode ( pas le prototype ;) ... du constructeur, ça ne marche pas, on me dit : illegal start of expression.

tu peux copier le code qui cause cette stp ?
1
Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013 660
9 déc. 2009 à 19:57
Et autant vérifier ça tout de suite : le nom du constructeur que tu as fait est-il bien le même que le nom de la classe (à la majuscule près ?) .
0
seljazou Messages postés 175 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 25 décembre 2009 1 > Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013
12 déc. 2009 à 14:44
oui, mais je crois que j'ai trouvé le problème..

Le constructeur de la classe Classe, on doit le mettre dans la classe Classe elle même. Moi je l'ai mis dans la fonction main, je croyais qu'on y fait appel dès quand utilise un objet.Mais dans un exemple de code, c'est pas ce que j'ai trouvé...
Je crois que je ferais mieux de lire un cours sur les constructeurs, et un cours très très détaillé. Je reviendrai surement :) poser des question après.

Merci
0
Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013 660 > seljazou Messages postés 175 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 25 décembre 2009
12 déc. 2009 à 15:45


Le constructeur de la classe Classe, on doit le mettre dans la classe Classe elle même. Moi je l'ai mis dans la fonction main, je croyais qu'on y fait appel dès quand utilise un objet.Mais dans un exemple de code, c'est pas ce que j'ai trouvé...
Je crois que je ferais mieux de lire un cours sur les constructeurs, et un cours très très détaillé. Je reviendrai surement :) poser des question après.


ah oui évidemment ! Le constructeur, c'est une méthode de classe spéciale. Elle est liée à la classe (puisqu'elle est appelée lorsqu'un nouvel objet est crée avec new Classe()) et donc est définie dans la classe.

je te conseille de chercher un cours sur la POO (Programmation Orientée Objet) en Java tout court. Les constructeurs y seront nécessairement abordés.
0
seljazou Messages postés 175 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 25 décembre 2009 1 > Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013
12 déc. 2009 à 17:20
J'ai un tout tout petit peu compris. et comme toujours, je dois parler pour
m'éclaircir les idées :

On a une classe Classe, on peut faire un constructeur ( parce que j'ai
lu qu'il y a un constructeur par defaut, donc on n'est pas obligés, je
crois).
je prends cet exemple

-----------------------------------------------------------------------------------------------------

public class Voiture {
private int puissance;
private boolean estDemarree;
private double vitesse;
public Voiture() {
puissance = 4;
estDemaree = false;
vitesse = 0;
}
public Voiture(int p) {
puissance = p;
estDemaree = false;
vitesse = 0;
}...
}
----------------------------------------------------------------------
mes questions dessus
- le constructeur doit t il contenir l'initialisation de tous les attribus ( public et private)? ou seulement quelques uns?
-Lorsqu'on a un constructeur par defaut, tout est initialisé à 0 ( ou NULL si c'est un String ou char)??
- dans l'exemple, lorsqu'on a dit puissance = 4 , est ce que ça veut dire en fait que dans la fonction main nous aurons objet.puissance = 4 ??? et si c'est le cas, c'est pas possible , parce que puissance est private, donc nous ne pourrons pas y avoir accès via l'objet, non???


Voici un autre programme qui a attiré mon attention ( et mes questions) :p

------------------------------------------------------------------------
public class Voiture {
...
private boolean estDemarree;
private double vitesse;
public int deQuellePuissance() {
...
}
public void accelere(double vitesse) {
if (estDemarree) {
this.vitesse = this.vitesse + vitesse;

--------------------------------------------------------------------------

J'arrive pas à comprendre :

1- L'utiliré de mettre des attributs private. Je lis partout que c'est pour les rendre invisibles depuis une autre classe, mais franchement ce n'est pas ttrop clair pou moi. je me répète mais je desespère :) , à quoi sert le private concrètement :(

2- On peut avoir accès à this.vitesse ?

3- dans le code, c'est if(estDemarré) pour dire if(objet.Demarré) ???



J'abuse, c'est trop de questions :( et j'ai beau chercher dans les sites, je trouve toujours cela vague, trop vague.

j'espère que tu me repondras.

Merci pour ton attention



0
Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013 660 > seljazou Messages postés 175 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 25 décembre 2009
12 déc. 2009 à 19:31
Pour la première partie :

- le constructeur doit t il contenir l'initialisation de tous les attribus ( public et private)? ou seulement quelques uns?

non, tu mets les initialisations que tu veux. Et aussi du code annexe si tu le souhaites (par exemple des System.out.println() pour voir dans la console que le constructeur a été appelé.


-Lorsqu'on a un constructeur par defaut, tout est initialisé à 0 ( ou NULL si c'est un String ou char)??

Oui. Attention, char c'est pas un objet, c'est un type de base qui est plus ou moins numérique. Il est initialisé à 0 aussi (le caractère nul '\0').


- dans l'exemple, lorsqu'on a dit puissance = 4 , est ce que ça veut dire en fait que dans la fonction main nous aurons objet.puissance = 4 ??? et si c'est le cas, c'est pas possible , parce que puissance est private, donc nous ne pourrons pas y avoir accès via l'objet, non???


Oui et non. Oui car en effet, la variable puissance du nouvel objet crée avec new vaudra effectivement 4. Et non comme tu dis : tu ne peux pas écrire objet.puissance dans main ni dans aucune autre fonction qui n'est pas une méthode de la classe car puissance est private. Par contre si tu appelles une méthode qui utilise cette variable (dans mon exemple d'avant j'avais fait un rectangle, ce serait par exemple si tu appelles rect1.calculerAire(), la méthode va utiliser les propriétés de l'objet, ses variables private, et elle utilisera bien 4 pour la puissance.



Pour le deuxième :

1- L'utiliré de mettre des attributs private. Je lis partout que c'est pour les rendre invisibles depuis une autre classe, mais franchement ce n'est pas ttrop clair pou moi. je me répète mais je desespère :) , à quoi sert le private concrètement :(


Oui c'est ce qui est pas facile à comprendre car pas utile apparemment.

En fait c'est une excellente pratique de génie logiciel (c'est à dire l'art de concevoir proprement un gros programme, comme le génie civil c'est concevoir proprement les routes etc...).

En cachant une variable (ou une méthode) en la désignant comme private, tu empeches "l'utilisateur de la classe" (ce qui est par exemple toi-même lorsque tu codes ton main() ) d'utiliser directement ça.

cela permet diverses choses, ou plutot ça permet d'interdire certaines choses. certaines choses qui seraient sources de bug potentielles.

Ex : si ta variable puissance est public, tu pourrais dans le main inscrire : objet.puissance = -8 .
Mais bien évidemment, si tu es censée créer un objet qui représente une voiture, cette valeur est absurde. Ou dans mon exemple, si tu mets la longueur du rectangle à -8 ce serait absurde aussi. ça causera des problèmes plus tard si tu appelles ma fonction calculerAire() : elle va donner un nombre négatif, et après si tu utilises cette valeur pour faire un autre calcul, le résultat serait surement absurde aussi etc... Tu ne verras le résultat que plus tard et tu passeras un temps considérable avant de voir que quelquepart perdu dans ton programme tu as écris "objet.puissance = -8" et que ce n'étais pas ce que tu voulais.

Dans le programme exemple que tu donnes, en fait on pourrais rajouter dans
public void accelere(double vitesse) {
  if (estDemarree) {
    this.vitesse = this.vitesse + vitesse;
  }
}


du code pour vérifier si la nouvelle vitesse donnée ne va pas être négative à la fin.

Ex : si vitesse vaut déjà 20 au départ, et que tu appelles dans le main :
objet.accelere(-10), alors pas de problème, la nouvelle vitesse de l'objet vaudra 10 et c'est tout bon. rien de spécial à faire.
mais si dans main() tu écris à la place : objet.accelere(-100), après cette méthode la vitesse vaudra -90, ce qui est absurde. A la limite on peut dire qu'on a ralenti la voiture à 0 de vitesse.

Alors on peut rajouter dans accelere un code pour vérifier cela :
public void accelere(double vitesse) {
  if (estDemarree) {
    if(this.vitesse + vitesse < 0) {
      thid-vitesse=0; // si vitesse finale négative, simplement mettre à zéro
    } else {
      this.vitesse = this.vitesse + vitesse; // sinon faire le calcul normal
    }
  }
}
}


tu remarqueras aussi que dans cette méthode la vitesse n'est pas modifiée si le moteur est éteint (ce serait aussi absurde).

Tous ces controles évitent "l'utilisateur" (toi quand tu codes le main() ou une autre fonction qui utilise l'objet) de faire des bêtises et cela permet au final d'éviter beaucoup de bugs. Ou en tout cas de rendre leur apparition plus claire.

ça parait un peu inutile, tu pourrais rétorquer : mais enfin c'est stupide je ne vais jamias faire ça dans mon main(), je sais très bien que c'est absurde.
Alors là je te répondrai "oui, mais non." Lorsque ton programme devient complexe (ce qui est le très vite le cas si tu veux faire qqchose de concret ), et que tu utilises plein de variables, c'est vite facile de faire une erreur.
Ou si tu automatise un programme qui va lire des valeurs dans un fichier, peut-être que certaines valeurs sont absurdes et tu auras des bugs plus tard si tu les laisses entrer comme valeur de ta fonction.

De plus, concretement, un programme est composé de plusieurs modules. Et souvent ce sont plusieurs personnes qui le codent. Ou encore tu vas utiliser des objets crée par d'autreS (code téléchargé sur le net par exemple). Tu n'as pas le temps ni l'envie de comprendre tout le code que tu as sous les yeux, que d'autres ont fait ou toi-même plusieurs mois avant et tu ne t'en souviens pas.

La programmation objet permet d'aider à résoudre ces risques et permet une programmation plus simple :
pour utiliser ta classe via les objets, tu ne fais appel dans le main() ou dans d'autres fonctions que uniquement aux méthodes public (ce qu'on appelle en français une interface). Si tu dois chercher de l'aide ou de la documentation sur une classe, tu ne dois regarder que les méthodes public. Ainsi, tu perds moins de temps à comprendre comment fonctionne un bout de code, et c'est plus propre car tu fais confiance au créateur de la classe d'avoir bien programmé tout ce qu'il faut, par exemple empêcher les valeurs absurdes dans les propriétés. Tout cela sans avoir à te soucier du détail de comment est programmé ton objet.

ça prend toute son utilité quand ton programme fait plusieurs centaines de lignes, avec plusieurs dizaines de classes.

N'hésite pas à poser plusieurs questions là-dessus si ce n'est toujours pas clair, et à faire des essais.

Je le répète encore une fois après ce gros monologue : on pourrait effectivement faire autrement, tout mettre public, et là on perd tout l'avantage de la philosophie de la prog objet qui permettait de bien compartimenter les différents bouts de code, et qui offrait une claire séparation entre l'interface (comment on utilise la classe dans main() par ex.) et l'implémentation (le détail du code dans la classe, par exemple comment la classe gère les accelerations de la voiture).


2- On peut avoir accès à this.vitesse ?

Dans les méthodes de classe uniquement. this fait référence à l'objet particulier sur lequel la méthode de classe est appelée. Mais depuis main() par ex. non, ça n'a pas de sens. D'une part car this ne veut rien dire dans ce cas, et d'autre part car vitesse est private justement.

3- dans le code, c'est if(estDemarre) pour dire if(objet.estDemarre) ???


oui en quelquesorte (sans accents ! ). Je dirais plutot this.estDemarre ;) .

N'oublie pas que cette méthode est définie dans la classe elle-même. C'est une méthode public (on peut appeler objet.accelere(10) depuis main() ) qui sert d'"interface" pour manipuler les propriétés de l'objet depuis l'extérieur (main() ) sans passer directement par les variables de l'objet depuis main().



J'abuse, c'est trop de questions


Certainement pas ! C'est un plaisir de te répondre, tu cherches beaucoup par toi même et tu poses des questions précises, c'est excellent pour toi pour apprendre, et c'est excellent pour ceux qui veulent te donner un coup de main comme moi.
0
Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013 660
12 déc. 2009 à 19:46
sinon en plus de mon gros blabla (désolé pour la longueur, j'espère que ça répond à tes questions) il faut aussi que tu apprennes à essayer par toi même. Bon c'est vrai c'est pas facile puisque tu en es aux bases, mais tout de même.

Compiler un petit code comme ça prend 3 secondes. Tu peux essayer de faire un programme test avec comme classe principale le programme test (qui sera la classe où il y a main() ). Et à coté tu fais une ou plusieurs classes à partir desquels tu vas instancier des objets dans main(). Et ensuite tu peux t'amuser à voir ce que diverses choses font, à grands coups de System.out.printf() .
public class Programme {
  public static main(String args[]) {
    //ici amuse toi à faire des tests et des affichages!
    //ex :
    ClasseTest objet1 = new ClasseTest();
    objet1.a = 35; // erreur de compilation si tu mets cette ligne... essaye ;)
    
    System.out.println("Valeur de a de objet1 = %d", objet.getA() );
    objet1.setA(10);
    System.out.println("Valeur de a de objet1 = %d", objet.getA() );
    
  }
}


public class ClasseTest {
  private int a;
  //constructeur de base
  public ClasseTest(void) {
    System.out.println("Constructeur ClasseTest(void) appelé");
    a=5; //idem que si tu mets this.a=5;
  }

  //autre constructeur pour directement initialiser a
  public ClasseTest(int a) {
    System.out.println("Constructeur ClasseTest(int) appelé");
    this.a = a;
  }

  //méthode pour lire la variable a
  public int getA() {
    return a;
  }

  //méthode pour changer la valeur de a
  public void setA(int a) {
    System.out.println("Appel à la méthode setA(int) avec paramètre %d", a);
    this.a = a;
  }
}


Bien entendu tu peux essayer plein de choses comme ça à l'infini !

Personne ne te mangera si tu fais des dizaines et des dizaines de petits essais, juste pour voir quelles erreurs apparaissent ou simplement voir ce qui se passe. ça t'aidera beaucoup à comprendre ;).
1
seljazou Messages postés 175 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 25 décembre 2009 1
13 déc. 2009 à 17:54
oui tu as raison, mon problème est que je n'ecris pas beaucoup de programmes. Auj je commencerai à faire quelques essais :) et toutes tes explications sont super ! et ce que tu as dit sur le génie logiciel est très interessant.

Mais promis, aujourd'hui je ferai des mini programmes, c'est la seule solution. J'ai déja pleins pleins de questions sur ce que m'as dit ( c'est pas que c'est pas clair ,au contraire, mais c'est que chacune de tes reponses me mène à d'autres "problématiques", d'autres cas à vérifier ....)

Pour le private, c'est un peu plus clair, mais avant de poser des questions :p je préfère essayer mes programmes ce soir et je ma baserai dessus pour mes questions. :)

Je ne pourrais jamais te remercier assez, tu m'aides énormément.


Merci++ :)



0