17
fév.
2010
fév.
2010
Java Quiz #32
Java / JEE ›
Java Quiz
|
Tags :
java
Par Olivier Croisier
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 !
public class Dragueur { private final String nom; private final Set<Demoiselle> aventures = new HashSet<Demoiselle>(); public Dragueur(String nom) { this.nom = nom; } public String getNom() { return nom; } public Set<Demoiselle> getAventures() { return Collections.unmodifiableSet(aventures); } boolean addAventure(Demoiselle e) { return aventures.add(e); } @Override public String toString() { return "Dragueur [nom=" + nom + ", aventures=" + aventures + "]"; } }
public class Demoiselle { private String nom; private Dragueur petitAmi; public Demoiselle(String nom, Dragueur petitAmi) { this.nom = nom; this.petitAmi = petitAmi; if (petitAmi != null) { petitAmi.addAVenture(this); } } public String getNom() { return nom; } public Dragueur getPetitAmi() { return petitAmi; } // equals() + hashCode() @Override public String toString() { return "Demoiselle [nom=" + nom + ", petitAmi=" + petitAmi + "]"; } }
public class Main { public static void main(String[] args) { Dragueur domJuan = new Dragueur("DomJuan"); Demoiselle falbala = new Demoiselle("Paris", domJuan); Demoiselle juliette = new Demoiselle("Juliette", domJuan); Demoiselle eree = new Demoiselle("Erée", domJuan); for (Demoiselle demoiselle : domJuan.getAVentures()) { System.out.println(demoiselle); } } }
(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
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.
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...
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 !
Joli !
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.
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 :)