ordre d'instanciation super/this/attributs

Le
ToOmS
Bonjour à tous,

S'il paraît logique, après tout, que les attributs "propres" d'une
classe soient initialisés après l'exécution du super-constructeur, il
me semble que ça n'était pas le cas Un projet démarré il y a
longtemps et qui fonctionnait, plante lamentablement en JDK 1.5.0_11 :

public class Toto extends Tata {
List attr = new ArrayList<Bibi>();

public Toto(HashMap args) {
super(args);
}
public void doSomething(List bibis) {
this.attr.putBibis(bibis); // NullPointerException !
}
}
public abstract class Tata {
public Tata(HashMap args) {
this.doSomething(args.get("liste_bibis"));
}
public abstract void doSomething(List bibis);
}

Comme on le voit, mon algorithme fait appel, via le super-constructeur
de la classe abstraite, aux attributs de la classe concrète qui ne
sont plus initialisés à temps.

A part de réaliser l'initialisation dans l'implémentation de
#doSomething, qq'un voit-il une manière plus élégante de mettre ce
programme au diapason de la nouvelle JVM ?
Merci d'avance, ToOmS.
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
TestMan
Le #229166
Bonjour à tous,

S'il paraît logique, après tout, que les attributs "propres" d'une
classe soient initialisés après l'exécution du super-constructeur, il
me semble que ça n'était pas le cas... Un projet démarré il y a
longtemps et qui fonctionnait, plante lamentablement en JDK 1.5.0_11 :

public class Toto extends Tata {
List attr = new ArrayList<Bibi>();

public Toto(HashMap args) {
super(args);
}
public void doSomething(List bibis) {
this.attr.putBibis(bibis); // NullPointerException !
}
}
public abstract class Tata {
public Tata(HashMap args) {
this.doSomething(args.get("liste_bibis"));
}
public abstract void doSomething(List bibis);
}

Comme on le voit, mon algorithme fait appel, via le super-constructeur
de la classe abstraite, aux attributs de la classe concrète... qui ne
sont plus initialisés à temps.

A part de réaliser l'initialisation dans l'implémentation de
#doSomething, qq'un voit-il une manière plus élégante de mettre ce
programme au diapason de la nouvelle JVM ?
Merci d'avance, ToOmS.



Bonjour,

L'ordre en Java est :
1- exécution du super-constructeur
2- initialisation des membres de l'instance
3- execution du reste du constructeur

Comme l'atteste la JLS 3e version
http://java.sun.com/docs/books/jls/third_edition/html/execution.html#44670
( y comprit la JLS 1e version
http://java.sun.com/docs/books/jls/first_edition/html/12.doc.html#44670 )

Pour ce qui concerne l'initialisation de votre exemple, pourquoi ne
mettez vous pas tout simplement l'appel du .doSomething dans le
constructeur de Toto ?

La régression applicative constatée, ne peut donc pas venir d'un
changement de spec, Java restant entierement compatible avec le code
ascendent (au rajouts de mots-clés et de syntaxe nouvelles près, mais
qu'il est possible de désactiver dans le compilateur pour une
compatibilité ascendente à 100%).

A+
TM

ToOmS
Le #229162
On 20 juin, 15:24, TestMan
[...]
Pour ce qui concerne l'initialisation de votre exemple, pourquoi ne
mettez vous pas tout simplement l'appel du .doSomething dans le
constructeur de Toto ?
[...]


Parce que #doSomething est un comportement surchargé mais attendu dans
Tata. J'en ait fait une méthode abstraite dans l'exemple pour aller au
plus lisible, mais les objets Tata doivent aussi "faire qq chose" à
l'instanciation.

Je ne comprends pas pourquoi Ca ne fonctionnait pas. Cette appli "a
eu" bien fonctionné, pourtant...
J'ai ajouté du code moche : si (this instanceof Toto) alors ((Toto)
this).initCollections(); puis this.doSomething().
#initCollections étant toujours appelé dans les autres constructeurs
de Toto.

Merci quand même !

Publicité
Poster une réponse
Anonyme