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

AWT/Swing Java Discussion :

variable dans ActionListener déclarer en final


Sujet :

AWT/Swing Java

  1. #1
    Membre éclairé Avatar de LeXo
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 147
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 147
    Points : 868
    Points
    868
    Par défaut variable dans ActionListener déclarer en final
    Bonjour

    voila je débute en java

    et je fais une sorte de tableau
    avec une classe perso FileToCopy

    le tableau est donc composé d'objet de la classe FileTopCopy
    et a chaque objet je lui mets un bouton qui va aller chercher un fichier avec un JFileChooser

    pour instancier un tel bouton, je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public JButton getButtonDetect(String name,FileToCopy fichier){
            JButton btDetect;
            btDetect = new JButton(name);
            btDetect.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e){
                    fichier.setPath();
                }
     
            }
            );
     
            return btDetect;
     
        }
    si j'ai bien compris fichier doit etre déclaré final ??
    pourquoi ??

    d'avance merci
    D:\Projet\Java\KTool\src\ihm\component\ArrayFileCopy.java:71: local variable fichier is accessed from within inner class; needs to be declared final
    Plzzz pas de questions par MP.

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Points : 635
    Points
    635
    Par défaut
    Tu déclare ton ActionListener en utilisant une classe anonyme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    new ActionListener(){
      public void actionPerformed(ActionEvent e){
        fichier.setPath();
      }
    Les variables utilisées par ces classes doivent être final

  3. #3
    Membre émérite
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Points : 2 582
    Points
    2 582
    Par défaut
    Cependant, moi je n'ai jamais compris pourquoi. Si quelqu'un avait des explications autre que C'est comme ça...
    Mieux que Google, utilisez Sur Java spécialisé sur la plate-forme java !
    Pour réaliser vos applications Java dans le cadre de prestations, forfait, conseil, contactez-moi en message privé.

  4. #4
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    292
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 292
    Points : 317
    Points
    317
    Par défaut
    Citation Envoyé par gifffftane Voir le message
    Cependant, moi je n'ai jamais compris pourquoi. Si quelqu'un avait des explications autre que C'est comme ça...
    l utilisation des variables d une methode dans une inner class doivent etre declare final.
    parceque les variable declare dans une methodes vivent dans le stack le probleme c est quand lorsque la methode se termine ces varaibles seront detruites, mais qu est ce qui se passent si ces variables sont detruites et que ton inner class est toujours en vie dans le Heap et sachant qu elle utilise une de ces vraiables??

    j espere que c est clair. pour plus d info consulter le chapitre 8 Inner Class de Sun certified Java Programer 5 study guide.

    Personnelement je trouve ce livre en genral est complet specialement si vous voulez passer la SCJP 1.5.

    Cheers,

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par gifffftane Voir le message
    Cependant, moi je n'ai jamais compris pourquoi. Si quelqu'un avait des explications autre que C'est comme ça...
    C'est juste pour éviter toute ambigüité...

    Le mot-clef final permet d'interdire toute nouvelle affectation de la variable et ainsi de garantir qu'elle "pointera" toujours vers le même objet. Ainsi il n'y a pas de doute sur l'objet qui sera manipulé dans la classe anonyme.


    En effet, si plus loin dans le code tu fais quelque chose du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fichier = new FileToCopy( ... );
    Alors il peut y avoir une ambigüité pour le développeur : la référence "fichier" dans la classe anonyme pointe-t-elle vers la première valeur ou bien vers cette nouvelle valeur ? Ce n'est pas évident à déterminer surtout que le code de la classe anonyme n'est pas forcément exécuté lors de sa déclaration (et en particulier pour un ActionListener).

    Bref en obligeant le final on est sûr de ne manipuler qu'une seule référence et il n'y a plus cette ambigüité !

    a++

  6. #6
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    292
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 292
    Points : 317
    Points
    317
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Bref en obligeant le final on est sûr de ne manipuler qu'une seule référence et il n'y a plus cette ambigüité !
    je me permet d ajouter, de ne pas perde la referance a cet objet aussi et le keep it life...

  7. #7
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par jhaythem Voir le message
    je me permet d ajouter, de ne pas perde la referance a cet objet aussi et le keep it life...
    La référence est passé à la classe anonyme via un constructeur implicite "coder" par le compilateur et conserver dans un attribut d'instance...

    Exemple :
    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
    		final Date date = new Date();
    		ActionListener al = new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				System.out.println(date);
    			}
    		};
     
     
    		System.out.println("Constructeur : ");
    		for (Constructor c : al.getClass().getDeclaredConstructors() ) {
    			System.out.println("\t"+c);
    		}
    		System.out.println("Attribut d'instance : ");
    		for (Field f : al.getClass().getDeclaredFields() ) {
    			System.out.println("\t"+f);
    		}
    Ce qui affiche :
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Constructeur : 
    	main.Main$1(java.util.Date)
    Attribut d'instance : 
    	private final java.util.Date main.Main$1.val$date
    (où "main.Main" correspond à ma classe de test)

    a++

  8. #8
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    292
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 292
    Points : 317
    Points
    317
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    La référence est passé à la classe anonyme via un constructeur implicite "coder" par le compilateur et conserver dans un attribut d'instance...

    Exemple :
    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
    		final Date date = new Date();
    		ActionListener al = new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				System.out.println(date);
    			}
    		};
     
     
    		System.out.println("Constructeur : ");
    		for (Constructor c : al.getClass().getDeclaredConstructors() ) {
    			System.out.println("\t"+c);
    		}
    		System.out.println("Attribut d'instance : ");
    		for (Field f : al.getClass().getDeclaredFields() ) {
    			System.out.println("\t"+f);
    		}
    Ce qui affiche :
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Constructeur : 
    	main.Main$1(java.util.Date)
    Attribut d'instance : 
    	private final java.util.Date main.Main$1.val$date
    (où "main.Main" correspond à ma classe de test)

    a++
    cool je savais pas ca merci pour l'info. donc la solution qu on trouve les concepteur c est de passer les variables utilise dans une inner class dans son contructeur, ca c est malin. ok je comprend mieux pourquoi ca doit etre final, merci pour la precision!!
    au fait voila un bout du livre Sun Certified Java Programmer 5 Study guide, bein leur explication mais pas aussi detaille que la tienne...

    Cheers,

    SUn Cerrtified Java Programmer 5 Study guide Chapter 8 Inner Class.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    However, the inner class object cannot use the local variables
    of the method the inner class is in. Why not?
    Think about it. The local variables of the method live on the stack, and exist only for
    the lifetime of the method. You already know that the scope of a local variable is
    limited to the method the variable is declared in. When the method ends, the stack
    frame is blown away and the variable is history. But even after the method
    completes, the inner class object created within it might still be alive on the heap if,
    for example, a reference to it was passed into some other code and then stored in an
    instance variable. Because the local variables aren't guaranteed to be alive as long
    as the method-local inner class object, the inner class object can't use them. Unless
    the local variables are marked final! The following code attempts to access a local
    variable from within a method-local inner class.

  9. #9
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    D'ailleurs ceci pourrait changer avec les closures... Je ne vois pas comment l'implémentation sera faite par contre, ça me parait un peu bizarre (notamment la possibilité qu'un return lève une exception au runtime - je n'ai plus le lien de la présentation des closures en slides commentées -).

  10. #10
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ®om Voir le message
    D'ailleurs ceci pourrait changer avec les closures... Je ne vois pas comment l'implémentation sera faite par contre, ça me parait un peu bizarre (notamment la possibilité qu'un return lève une exception au runtime - je n'ai plus le lien de la présentation des closures en slides commentées -).
    http://www.javac.info/


    D'après ce que j'ai compris, les closures seront associées au contexte du bloc qui l'a invoqué et pourra donc manipuler les mêmes variables et des mots-clefs comme this, break, continue ou return en relation avec le bloc parent.

    Bien entendu cela nécessitera que le code soit exécuté dans le même thread et avant la fin du bloc. Et si ce n'est pas le cas une exception sera remontée (UnmatchedNonlocalTransfer).

    A noter également l'existence d'une interface RestrictedFunction"qui permettra d'appliquer à une closures les mêmes restrictions que les classes anonymes...

    a++

  11. #11
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Bien entendu cela nécessitera que le code soit exécuté dans le même thread et avant la fin du bloc.
    D'après ce que j'ai compris, justement, pas forcément dans le même thread... D'ailleurs le mec répondait à une question indiquant que si une variable était accédée dans la closure et dans le code "normal" par 2 thread différents, il faudrait synchroniser l'accès. Et si c'était dans un seul thread, il n'y aurait pas de problème de return...

    EDIT: le lien : http://developers.sun.com/learning/j...r=2007&track=5
    Cliquez sur watch multimedia (il faut être loggué). (d'ailleurs c'est cool maintenant y'a le texte à côté, en plus de l'écoute)

  12. #12
    Membre émérite
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Points : 2 582
    Points
    2 582
    Par défaut
    Donc, pour résumer, seulement au niveau des inners classes (parce que les colures j'y suis pas encore, moi, hein), :

    - bien évidemment que les variables locales sont dans le stack et se perdent au retour !

    - bien évidemment que avec ce système en l'état elles seraient perdues pour la inner classe !

    - l'astuce est de les passer automatiquement dans un constructeur masqué (et d'ailleurs je crois qu'on n'a pas le droit de mettre de constructeur pour les classes inner, donc il y a là une double astuce), et donc les variables locales se trouveraient copiées en variables attributs (eux aussi masqués, d'ailleurs).

    ... mais alors je vois toujours pas l'intérêt des final ?? Les variables qui sont dans le tas lorsqu'elles sont locales, grâce à l'astuce du constructeur masqué, se retrouveraient dans je ne sais quelle zone pour les attributs, et de fait conservées, même après le retour de la méthode ??
    Mieux que Google, utilisez Sur Java spécialisé sur la plate-forme java !
    Pour réaliser vos applications Java dans le cadre de prestations, forfait, conseil, contactez-moi en message privé.

  13. #13
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par gifffftane Voir le message
    ... mais alors je vois toujours pas l'intérêt des final ?? Les variables qui sont dans le tas lorsqu'elles sont locales, grâce à l'astuce du constructeur masqué, se retrouveraient dans je ne sais quelle zone pour les attributs, et de fait conservées, même après le retour de la méthode ??
    En effet le final pourrait être complètement inutile pour le compilateur, mais cela permet d'éviter certaines ambigüité pour le développeurs.

    A moins de connaitre en détail ce mécanisme, le développeur peut penser qu'il n'y a qu'une seule et unique référence alors qu'en vérité il y en a deux bien distinctes. Donc ci tu modifies la référence d'une variable tu n'impacteras pas la seconde ce qui fait qu'on peut être amené à coder des truc comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	String toto = "TOTO";
    	new ActionListener() {
    		public void actionPerformed(ActionEvent e) {
    			toto = "TATA"; 
    		}
    	};
    On peut penser que l'actionListener modifie la variable locale "toto" mais en fait cela n'impacte que son attribut "copie".


    Et à l'inverse :
    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
    17
    18
    	String toto = "TOTO";
     
    	new Thread() {
    		public void run() {
    			while (true) {
    				System.out.println(toto);
    				Thread.sleep(1000);
    			}
    		}
    	}.start();
     
    	toto = "TITI";
     
    	...
     
    	toto = "TATA";
     
    	...
    On peut penser que le thread affichera les différentes valeurs de toto mais une fois de plus il n'en est rien...


    Bref tout les problèmes concerne la modification de la valeur de la référence, donc forcer le final permet de mettre en garde contre ce type de problème dès la compilation !


    a++

  14. #14
    Membre émérite
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Points : 2 582
    Points
    2 582
    Par défaut
    Bon si c'était moi qui avait posé la question j'aurais mis résolu
    Mieux que Google, utilisez Sur Java spécialisé sur la plate-forme java !
    Pour réaliser vos applications Java dans le cadre de prestations, forfait, conseil, contactez-moi en message privé.

  15. #15
    Membre éclairé Avatar de LeXo
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 147
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 147
    Points : 868
    Points
    868
    Par défaut et bien
    je viens de revenir sur le forum

    et j'avoue que moi ça m'intéressait d'avoir plus détaillé

    merci giffftane et tous les participants à cette discussion
    Plzzz pas de questions par MP.

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

Discussions similaires

  1. [Debutant]Comment déclarer des variables dans un fichier a part
    Par megapacman dans le forum Général Java
    Réponses: 14
    Dernier message: 14/01/2008, 13h32
  2. déclarer une variable dans tout un module
    Par Swiper dans le forum Macros et VBA Excel
    Réponses: 13
    Dernier message: 02/07/2007, 09h06
  3. Déclarer une variable dans un PIC
    Par Vinch006 dans le forum C
    Réponses: 5
    Dernier message: 09/03/2007, 17h49
  4. Réponses: 4
    Dernier message: 20/04/2006, 02h56
  5. [AS2] déclarer des variables dans une fonction
    Par ooyeah dans le forum ActionScript 1 & ActionScript 2
    Réponses: 12
    Dernier message: 02/08/2005, 12h50

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