IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Initialisation de membres lors de leur définition.


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Avatar de JMLLB
    Inscrit en
    Septembre 2006
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 285
    Par défaut Initialisation de membres lors de leur définition.
    Bonjour à tous,

    Jai un sérieux doute sur le moment où est effectué l'initialisation d'un membre lorsque l'on déclare une valeur par défaut lors de sa déclaration.
    Il me semblait que ça se faisait lors de la création d'un nouvel objet possédant ces membres avant d'arriver dans son constructeur
    (mais sans doute pas avant son super constructeur).

    J'ai commencé une appli où je déclarais jusqu'à lors mes ActionListener comme des membres de ma classe les utilisants (appelons là "classPipo").
    Je les définissais dans la foulée et lorsque je devais les associer avec un objet quelconque je faisais référence au membre.
    Pour résumer, une fois que l'on a enlevé tout ce qui est en dehors du sujet présent, ça donne à peu près ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class classPipo extends JFrame{
        protected JButton avatarButton;
        protected ActionListener globalActionMember = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.out.println("globalActionMember: Action ["+e.getActionCommand()+"] performed!\n");
            }
        };
        classPipo(){
           super();
           Container contents = getContentPane();
           this.avatarButton=new JButton();
           this.avatarButton.addActionListener(globalActionMember);
           contents.add(this.avatarButton);
        }
    }
    Jusque là rien de bien exotique et le comportement était celui attendu.
    Un beau jour (hier pour être précis) je me suis lancé dans une opération de réorganisation de mon code de manière à faciliter la maintenance
    (oui, je sais que 90% des problèmes viennent de ce genre de bonnes intentions ).
    En cours de route je me suis rendu compte que certaines l'action ne déclenchait plus du tout .
    A force de chercher je me suis appercu qu'une init dans le constructeur réglait mon problème.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class classPipo extends JFrame{
        protected JButton avatarButton;
        protected ActionListener globalActionMember;
        classPipo(){
           super();
           Container contents = getContentPane();
           this.globalActionMember = new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                System.out.println("globalActionMember: Action ["+e.getActionCommand()+"] performed!\n");
              }
           };
           this.avatarButton=new JButton();
           this.avatarButton.addActionListener(globalActionMember);
           contents.add(this.avatarButton);
        }
    }
    Ou encore si j'utilise une classion pour la gestion de mes action ça marche aussi nickel.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class classPipo extends JFrame{
        protected JButton avatarButton;
        protected class globalActionClass implements ActionListener {
    	public globalActionClass(){super();}
            public void actionPerformed(ActionEvent e) {
                System.out.println("globalActionClass: Action ["+e.getActionCommand()+"] performed!\n");
            }
        };
        classPipo(){
           super();
           Container contents = getContentPane();
           this.avatarButton=new JButton();
           this.avatarButton.addActionListener(new globalActionClass());
           contents.add(this.avatarButton);
        }
    }
    Mais en tout état de cause ça ne m'explique pas pourquoi la première version ne fonctionne pas (ou plus).
    Il y a donc quelque chose qui m'échape sur l'ordre d'initialisation et ce n'est pas sans me rappeler des problèmes de "rincage" de variables que je n'avais pas pris le temps de creuser et qui resemblaient beaucoup à des initialisations arrivant après l'entrée dans le constructeur .

    Si vous avez les idées plus claires que moi sur ces problèmes d'init je suis preneur de vos éclaircissements .

    merci,
    JLB

    Pour info: NetBeans IDE 5.0/Linux v 2.6.11 (running on i386)/Java jdk1.5.0_06

  2. #2
    Membre éclairé
    Avatar de JMLLB
    Inscrit en
    Septembre 2006
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 285
    Par défaut Confirmation
    Mon problème de rincage de variable inopportun se confirme.

    Une initialisation à null d'un objet membre la de sa déclaration est effectuée après l'entrée dans le constructeur (avec tout les désagréments que cela suppose...).
    C'est en tout cas ce que j'ai vu sous le déboggeur (pour qui j'ai une confiance limité) et qui est confirmé par le fait que l'init à null en moins tout se passe bien.
    Pourtant cet objet n'est même pas static et devrait donc avoir une init standart.

    J'ai donc un comportement assez différent de ce à quoi je m'attendais après avoir lu cet article :
    http://bruce-eckel.developpez.com/li...?chap=5&page=3

    Il y a certainement une explication logique mais en attendant je vais fuir comme la peste les inits hors constructeur.

  3. #3
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    j'ai pas tout lu (je suis à la bourre) mais voilà la structure d'un constructeur

    1) appel de super (implicite ou explicite) ou de this
    2) initialisation des variables membres (et/ou des blocs d'initialisations)
    3) suite du code

    donc toute méthode appelée dans un code "passe" après les initialisations des variables membres mais en cas d'héritage on peut avoir des effets drolatiques du fait du rappel de ces intialisations dans le constructeur de la classe -mère.

    edit: j'ai regardé ton premeri code: l'instance de Listener est crée AVANT que le bouton existe! (applique la règle ci-dessus)

  4. #4
    Membre éclairé
    Avatar de JMLLB
    Inscrit en
    Septembre 2006
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 285
    Par défaut A force de simplifier...
    Bon j'ai compris!

    L'exemple de code que j'ai fourni ne doit pas servir à grand chose car dans un soucis de simplification je n'ai pas reproduit l'héritage présent dans mon code véritable.
    Donc selon toute probabilté il doit fonctionner.

    Après avoir lu ton post je pense que le comprotement que j'observe est à classer dans les : "effets drolatiques" comme tu dis.
    En effet tout le séquencement des fonctions d'init est fait dans la classe mère, même si les fonctions d'init sont surchargées dans la classe fille.
    Or, pas de bol, dans une fonction d'init je faisais le lien entre le bouton que je venais de créer et l'ActionListener qui lui n'existait pas encore, puisqu'il serait créé après la sortie du constructeur de la classe mère.

    Ca change un peu ma conclusion précédante :
    fuir comme la peste les inits avec les déclarations!

    Merci pour tes explications!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [2.0] Créer des types & modifier leur définition par code
    Par FRED.G dans le forum Framework .NET
    Réponses: 6
    Dernier message: 12/11/2006, 17h49
  2. Réponses: 4
    Dernier message: 18/05/2006, 09h56
  3. initialiser les membres d'une structure
    Par molesqualeux dans le forum C
    Réponses: 8
    Dernier message: 02/02/2006, 19h57

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo