Vous aimez ce que vous lisez sur ce blog ?
Envie d'aller plus loin avec véritable formation d'expertise en Java ?
Venez suivre ma formation Masterclasse Expertise Java !

"Même un développeur experimenté a besoin de continuer à apprendre. Et dans cette formation... j'ai appris beaucoup !" - A.G., Java Champion

Sessions intra-entreprises sur demande : contact[at]mokatech.net.
Inscrivez-vous vite !

Java Quiz #32

Voici un quiz spécial saint-Valentin ! Comme d'habitude, il s'agit de trouver ce qui cloche avec ce code, sans le coller dans un IDE.

Comme le code est un peu plus long que d'habitude, il est exceptionnellement dans le corps du billet.
Bon quiz !

  1. public class Dragueur {
  2.  
  3. private final String nom;
  4. private final Set<Demoiselle> aventures = new HashSet<Demoiselle>();
  5.  
  6. public Dragueur(String nom) {
  7. this.nom = nom;
  8. }
  9.  
  10. public String getNom() {
  11. return nom;
  12. }
  13.  
  14. public Set<Demoiselle> getAventures() {
  15. return Collections.unmodifiableSet(aventures);
  16. }
  17.  
  18. boolean addAventure(Demoiselle e) {
  19. return aventures.add(e);
  20. }
  21.  
  22. @Override
  23. public String toString() {
  24. return "Dragueur [nom=" + nom + ", aventures=" + aventures + "]";
  25. }
  26. }
  1. public class Demoiselle {
  2.  
  3. private String nom;
  4. private Dragueur petitAmi;
  5.  
  6. public Demoiselle(String nom, Dragueur petitAmi) {
  7. this.nom = nom;
  8. this.petitAmi = petitAmi;
  9. if (petitAmi != null) {
  10. petitAmi.addAVenture(this);
  11. }
  12. }
  13.  
  14. public String getNom() {
  15. return nom;
  16. }
  17.  
  18. public Dragueur getPetitAmi() {
  19. return petitAmi;
  20. }
  21.  
  22. // equals() + hashCode()
  23.  
  24. @Override
  25. public String toString() {
  26. return "Demoiselle [nom=" + nom + ", petitAmi=" + petitAmi + "]";
  27. }
  28. }
  1. public class Main {
  2.  
  3. public static void main(String[] args) {
  4. Dragueur domJuan = new Dragueur("DomJuan");
  5. Demoiselle falbala = new Demoiselle("Paris", domJuan);
  6. Demoiselle juliette = new Demoiselle("Juliette", domJuan);
  7. Demoiselle eree = new Demoiselle("Erée", domJuan);
  8. for (Demoiselle demoiselle : domJuan.getAVentures()) {
  9. System.out.println(demoiselle);
  10. }
  11. }
  12.  
  13. }

(Note: on peut ajouter mais pas supprimer une conquête de Dom Juan :)

Réponse : Ce code provoque une StackOverflowError, à cause des références croisées entre les classes Dragueur et Demoiselle dans les méthodes toString().
Ce problème peut survenir très rapidement si l'on utilise des générateurs de code, comme celui d'Eclipse par exemple. Restez donc vigilants lors que vous les utilisez !


Commentaires

1. Le mercredi 17 février 2010, 14:00 par Benoît

C'est peu être pas ça (ça montre comment je suis sûr de moi), mais si on a deux épouses avec le même nom, pour le même Mari, comme les méthodes equals et hashcode sont a priori basées sur ces deux attributs, une épouse peut ne pas être ajoutée à la liste des épouses, si elle a le même nom qu'une épouse déjà présente.

2. Le mercredi 17 février 2010, 14:04 par romaintaz

Le problème vient des méthodes toString() qui s'appellent l'une et l'autre. Le toString() de l'épouse va appeller le toString() du mari, qui lui même va appeller le toString() de chacune des épouses. Donc ça sent le StackOverflow ça...

3. Le mercredi 17 février 2010, 14:49 par Olivier Croisier

Effectivement, StackOverflowError...

Mine de rien, je me suis déjà laissé piéger par ce problème stupide : j'avais laissé Eclipse générer les toString() pour débugger un algorithme épineux, et du coup un nouveau problème s'est ajouté au premier, brouillant les pistes encore davantage. A n'y plus rien comprendre !
J'ai cherché longtemps avant de réaliser que ça venait des toString()...

Comme quoi, méfiez-vous de la génération de code !

4. Le jeudi 18 février 2010, 08:57 par Piwaï

Joli !

5. Le jeudi 18 février 2010, 14:35 par Frederic Merizen

Joli, je n'avais pas vu venir la stack overflow.

Mais je crois qu'il y a un petit souci avec le nom du constructeur de Demoiselle.

6. Le jeudi 18 février 2010, 14:48 par Olivier Croisier

Ah merci, j'ai corrigé.
Les deux classes sont passées par différents noms avant d'avoir ceux-ci, adaptés pour la Saint-Valentin :)

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.