Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

ordre d'instanciation super/this/attributs

2 réponses
Avatar
ToOmS
Bonjour =E0 tous,

S'il para=EEt logique, apr=E8s tout, que les attributs "propres" d'une
classe soient initialis=E9s apr=E8s l'ex=E9cution du super-constructeur, il
me semble que =E7a n'=E9tait pas le cas... Un projet d=E9marr=E9 il y a
longtemps et qui fonctionnait, plante lamentablement en JDK 1.5.0_11 :

public class Toto extends Tata {
List attr =3D 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=E8te... qui ne
sont plus initialis=E9s =E0 temps.

A part de r=E9aliser l'initialisation dans l'impl=E9mentation de
#doSomething, qq'un voit-il une mani=E8re plus =E9l=E9gante de mettre ce
programme au diapason de la nouvelle JVM ?
Merci d'avance, ToOmS.

2 réponses

Avatar
TestMan
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

Avatar
ToOmS
On 20 juin, 15:24, TestMan wrote:
[...]
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 !