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 :

classe anonyme et paramétre final


Sujet :

Langage Java

  1. #1
    Membre averti
    Avatar de natoine
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Décembre 2007
    Messages
    393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Décembre 2007
    Messages : 393
    Points : 343
    Points
    343
    Par défaut classe anonyme et paramétre final
    Bonjour à tous,
    alors voilà je pose la question suivante :
    Pourquoi est-ce que les variables locales externes à l'instance de la classe anonyme doivent être finales ?

    Je sais que ça garantit que la classe anonyme ne puisse pas modifier ces variables mais je ne comprends pas l'intérêt.

    C'est encore pire pour le paramétre passé en appel de la méthode dans laquelle est définie ma classe anonyme. Je ne comprends pas à quoi ça sert qu'il soit final puisque de toute façon si on modifiait la valeur de ce paramétre dans la méthode, on ne ferait que modifier une copie du paramétre ...

    Un exemple de code avec classe anonyme.

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    public class WithAnonymousClass 
    {
        int b=80;
     
        void method(final int a){
            final int r = a + 1 ;
            ForAnonymousClass t = new ForAnonymousClass()
            {
                int c = a;
                public void doStuff()
                {
                    c++;
                    b = r + 1;
                    System.out.println("doStuff de ForAnonymousClass, valeur de b :" + b + " valeur de c : " + c);
                }
                public void doSomethingElse()
                {
                    b ++ ;
                    System.out.println("doSomethingElse de ForAnonymousClass");
                }
            } ; 
            t.doStuff();
            //t.doSomethingElse(); //inconnu car non défini dans l'interface, pourtant la méthode est public ...
            OtherClass other_class = new OtherClass()
            {
                int k = 7 ;
                public void doOtherStuff() 
                {
                    super.doOtherStuff();
                    System.out.print("doOtherStuff dans re définition de OtherClass"); 
                } ;
            };
            other_class.doOtherStuff() ;
        }
     
        public static void main(String[] args)
        {
            WithAnonymousClass b = new WithAnonymousClass();
            int param = 0;
            b.method(param);
        }
    }

  2. #2
    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,


    Lorsque tu accèdes à une variable locale depuis une classe anonyme, tu accèdes en réalité à une copie qui est implicitement passé en paramètre au constructeur de ta classe anonyme.

    Du coup les modifications apportées dans la classe anonyme ne sont pas visible par le reste de la méthode, ce qui pourrait être source d'erreur. Pour éviter de tel ambiguïté ces variables doivent être déclarées final.

    a++

  3. #3
    Membre averti
    Avatar de natoine
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Décembre 2007
    Messages
    393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Décembre 2007
    Messages : 393
    Points : 343
    Points
    343
    Par défaut
    Merci pour ta réponse.

    hum mais attends là, chaque fois que je définis une méthode en java, je sais que dans le corps de ma méthode je vais travailler sur une copie de mes paramétres et que du coup, mes modifications ne seront pas visibles en dehors de ma méthode.
    Pourquoi alors, avec la même logique que celle que tu m'énonces, je ne devrai pas déclarer tous mes paramétres final ?

  4. #4
    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
    C'est un choix qui a été fait c'est tout...


    Lorsque tu appelles un méthode, le passage de paramètre est explicite dans le code.

    Lorsque tu utilises une variable locale dans une classe anonyme, le passage de paramètre est implicite et n'apparait pas dans le code. Du coup cela peut prêter à ambiguïté.


    a++

  5. #5
    Membre averti
    Avatar de natoine
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Décembre 2007
    Messages
    393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Décembre 2007
    Messages : 393
    Points : 343
    Points
    343
    Par défaut
    Ok. Bien reçu. Là je comprends.

  6. #6
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Points : 410
    Points
    410
    Par défaut
    Citation Envoyé par natoine Voir le message
    Pourquoi est-ce que les variables locales externes à l'instance de la classe anonyme doivent être finales ?
    Bonjour,

    Il est probable que je me trompe, mais ce problème pourrait selon moi n'avoir aucun rapport avec le fait que la classe soit anonyme (cf capture d'écran).

    Any local variable, formal method parameter or exception handler parameter used but not declared in an inner class must be declared final. Any local variable, used but not declared in an inner class must be definitely assigned (§16) before the body of the inner class
    cf ici

    Toutes mes excuses si je fais erreur.

    Cela ne remet pas du tout la réponse d'AdiguBa en question, puisqu'elle est toujours valable si on remplace "anonyme" par "inner".

    Le problème ne vient que du fait que la classe continue à exister hors de la portée de la méthode, et donc hors de la durée de vie de la variable locale. Il n'est donc pas possible de conserver une référence sur cette variable à l'intérieur de la classe.

    Merci d'avoir lu.
    Images attachées Images attachées  

  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
    Une classe anonyme est une inner-classe... donc je ne vois pas ce que ca change

    a++

  8. #8
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 565
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 565
    Points : 21 630
    Points
    21 630
    Par défaut
    Bah, comme il le dit, ça n'a pas à voir avec le fait que la classe soit anonyme... Mais avec le fait que ça soit une inner class .

  9. #9
    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
    Dans 99% des cas, les inner-classes qui accèdent à des variables locales sont des classes anonymes.

    J'ai rarement vu des inner-classes non-anonymes déclarées à l'intérieur d'une méthode...

    a++

  10. #10
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    bien vu elvin, grâce à toi, je viens de découvrir qu'on pouvait écrire cette horreur qui, je dois l'admettre, me permettra peut-être un jour de palier à l'absence de constructeur dans une anonymous inner class (bon prendre un rendez-vous chez un psy maintenant, j'ai raté mon jet de SAN)


    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    public class TestInner {
     
        Object o;
        public void test(String a){
            final String test = a;
            class Inner {
                String param;
                public Inner(String param){
                    this.param=param;
                }
                public String doTest(){
                    return test+" -> "+param;
                }
            }
            String test2 = "12345";
            Inner in = new Inner(test2);
            o = in;
            System.out.println(in.doTest());
        }
        public static void main(String[] argv){
            try {
                TestInner in = new TestInner();
                in.test("blablabla");
                System.out.println(in.o.getClass());
                Constructor c = in.o.getClass().getDeclaredConstructors()[0];
                Method m = in.o.getClass().getMethod("doTest");
                System.out.println(m.invoke(c.newInstance(in,"444","719")));
            } catch (InstantiationException ex) {
                Logger.getLogger(TestInner.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                Logger.getLogger(TestInner.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalArgumentException ex) {
                Logger.getLogger(TestInner.class.getName()).log(Level.SEVERE, null, ex);
            } catch (InvocationTargetException ex) {
                Logger.getLogger(TestInner.class.getName()).log(Level.SEVERE, null, ex);
            } catch (NoSuchMethodException ex) {
                Logger.getLogger(TestInner.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SecurityException ex) {
                Logger.getLogger(TestInner.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
     
    }
    Au fond de moi, quelque chose viens de mourir

  11. #11
    Membre chevronné
    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 : 75
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Points : 1 855
    Points
    1 855
    Par défaut
    Citation Envoyé par Feriaman Voir le message
    Le problème ne vient que du fait que la classe continue à exister hors de la portée de la méthode, et donc hors de la durée de vie de la variable locale. Il n'est donc pas possible de conserver une référence sur cette variable à l'intérieur de la classe.
    si la classe interne liée à l'instance courante(quelle quelle soit) garde une référence vers une variable membre de l'instance englobante on n'a pas cette nécessité.
    Si c'est quelque chose alloué sur la pile c'est pas la même histoire
    Dans un cas le nouvel objet peut accéder par reférenceEnglobante.champ dans l'autre c'est une copie qui est passée et donc il ne faut pas espérer qu'une modification dans le code englobant soit répercuté dans le nouvel objet.
    C'est ça?

  12. #12
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Citation Envoyé par professeur shadoko Voir le message
    C'est ça?
    Ben oui, d'ailleurs si tu regarde le code que j'ai donné à se flinguer, par "réflection", le constructeur prend 3 paramètres et non pas 1. Sont rajoutés au constructeur: le paramètre final ainsi que l'instance englobante Le final ne serait théoriquement pas une nécessité, tant qu'on garde conscience qu'il y a une copie. Mais dans ce genre de code, alors, il y aurait je pense ambiguité :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        public void test(String a){
            String test = a;
            class Inner {
                public String doTest(){
                    return test+" -> "+param;
                }
            }
            test = "444719";
            new Inner().doTest(); // quelle valeur de "test" serait passée au constructeur?
        }

  13. #13
    Invité
    Invité(e)
    Par défaut
    Une solution qui peut être mise en place pour pallier à ce problème est d'analyser si la variable n'est pas finale et est de type immuable, de passer un object Wrapper contenant la variable et de traduire toutes les utilisations de cette variable par des utilisations du wrapper (dans la méthode comme dans la classe anonyme). Ainsi la classe anonyme peut changer la valeur de la variable mais aussi répondre aux changements dans la méthode.

    Sinon tchize_: pour pallier à l'absence de constructeur pour les classes anonymes, tu peux toujours utiliser un bloc d'initialisation, j'ai déjà vu un truc comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Map<String, String> map = new HashMap<String, String>() {
      {
        put("test", "test");
        put("hop", "yep");
      ...
      }
    };
    C'est pas top mais ça n'utilise pas la réflection

  14. #14
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    oui je connais, mais on reste sur le problème de base alors, pas question d'utiliser autre chose que des finals. Hors à un constructeur tu peux lui passer autre chose :p

  15. #15
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    oui je connais, mais on reste sur le problème de base alors, pas question d'utiliser autre chose que des finals. Hors à un constructeur tu peux lui passer autre chose :p
    Anéfé
    La solution avec un wrapper est utilisée par le compilo scala, on peut utiliser des var ou des val indifféremment dans une classe interne ou méthode interne ou une closure (qui sont des classes internes au final). Le problème se pose avec les closures en Java aussi

  16. #16
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Points : 410
    Points
    410
    Par défaut
    Citation Envoyé par professeur shadoko Voir le message
    si la classe interne liée à l'instance courante(quelle quelle soit) garde une référence vers une variable membre de l'instance englobante on n'a pas cette nécessité.

    Si c'est quelque chose alloué sur la pile c'est pas la même histoire

    Dans un cas le nouvel objet peut accéder par reférenceEnglobante.champ dans l'autre c'est une copie qui est passée et donc il ne faut pas espérer qu'une modification dans le code englobant soit répercuté dans le nouvel objet.
    C'est ça?
    Cette description me semble correcte.

    La seule chose sur laquelle je ne m'engagerais pas c'est sur le terme "copie". Il me semble que c'est AdiGuba qui a introduit se terme, et je pense qu'on peut lui faire confiance.

    Moi j'imaginais plutôt que que les variables finales étaient en réalité stockées dans un espace à part qui leur est propre.
    En tout cas, c'est le cas pour les programmes C++ compilés (le Data segment).
    Et en effet, il ne semble pas très intéressant de se balader avec trente copies de la même variable finale en mémoire, alors que justement elle est finale.

    Cela dit, cet article sous-entend que c'est plus compliqué que cela dans la JVM. Du coup, je n'ai aucune certitude.

    Citation Envoyé par George7
    Sinon tchize_: pour pallier à l'absence de constructeur pour les classes anonymes, tu peux toujours utiliser un bloc d'initialisation, j'ai déjà vu un truc comme ça :
    Je ne comprends pas pourquoi vous voulez absolument utiliser des classes anonymes, et bidouiller un constructeur, alors que le Java propose justement le mécanisme des Inner Classes pour répondre à cela.
    Pour moi, une inner classe définie dans une fonction fait exactement comme une classe anonyme, mais avec un constructeur.

    [EDIT]D'ailleurs, c'est précisément le point sur lequel adiGuba insistait plus haut : les classes anonymes sont des inner classes sans nom et avec des constructeurs implicites[/EDIT]

  17. #17
    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 Feriaman Voir le message
    La seule chose sur laquelle je ne m'engagerais pas c'est sur le terme "copie". Il me semble que c'est AdiGuba qui a introduit se terme, et je pense qu'on peut lui faire confiance.
    Les variables locales sont passées implicitement au constructeur de l'inner-classe. Le passage de paramètres se fait par copie. Bien sûr si on passe un objet on ne copie que la référence et non pas l'objet en lui-même.

    Citation Envoyé par Feriaman Voir le message
    Moi j'imaginais plutôt que que les variables finales étaient en réalité stockées dans un espace à part qui leur est propre.
    En tout cas, c'est le cas pour les programmes C++ compilés (le Data segment).
    Et en effet, il ne semble pas très intéressant de se balader avec trente copies de la même variable finale en mémoire, alors que justement elle est finale.
    La copie ne concerne que la référence et non pas l'objet en lui-même.
    Après il faut distinguer les variables finales et les constantes qui sont stocké directement dans la classe.

    Citation Envoyé par Feriaman Voir le message
    Cela dit, cet article sous-entend que c'est plus compliqué que cela dans la JVM. Du coup, je n'ai aucune certitude.
    Heu... on n'est plus dans le même sujet là non ?


    Citation Envoyé par Feriaman Voir le message
    Je ne comprends pas pourquoi vous voulez absolument utiliser des classes anonymes, et bidouiller un constructeur, alors que le Java propose justement le mécanisme des Inner Classes pour répondre à cela.
    Si tu accèdes à des variables locales, cela signifie que tu dois déclarer la classe dans le corps d'une méthode. Dans ce cas là on utilise généralement une classe anonyme...

    Citation Envoyé par Feriaman Voir le message
    Pour moi, une inner classe définie dans une fonction fait exactement comme une classe anonyme, mais avec un constructeur.
    Et tu le fait souvent ? Perso c'est le genre de code que je vois très peu !!!

    a++

  18. #18
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Points : 410
    Points
    410
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Les variables locales sont passées implicitement au constructeur de l'inner-classe.
    Tu l'affirmes, et encore une fois : a priori, je te fais confiance.
    Mais ça m'intéresse de savoir où tu as trouvé cette information.

    Citation Envoyé par adiGuba Voir le message
    Heu... on n'est plus dans le même sujet là non ?
    Au contraire : dans la question 6b, l'initialisation de la variable statique j a visiblement lieu avant le constructeur de "Derived", alors que la règle dit qu'il devrait avoir lieu après.

    J'en déduis que les variables finales sont initialisées différemment des variables non-finales (ce qui est confirmé par la règle puisqu'elles ont lieu avant).

    Une des raisons que j'imagine (et là tu as raison, il ne s'agit que de mon imagination), c'est qu'elles sont pré-initialisées avant le lancement du programme. Et elles sont pré-initialisées parce qu'elles ne sont pas rangées au même endroit que les autres en mémoire.

    J'imagine ceci, parce qu'en C++, c'est comme ça que ça marche.


    Citation Envoyé par adiGuba Voir le message
    Dans ce cas là on utilise généralement une classe anonyme...
    Et tu le fait souvent ? Perso c'est le genre de code que je vois très peu !!!
    Je ne comprends pas cet argument.
    Java prévoit cette solution pour gérer ce besoin.
    Pour moi la question ne se pose pas : si j'ai ce besoin j'utilise cette solution.

    La question : est-ce que d'autres gens l'utilise beaucoup ou pas beaucoup n'a rien à voir là-dedans.
    La bonne pratique n'est pas un concours de popularité.

  19. #19
    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 Feriaman Voir le message
    Tu l'affirmes, et encore une fois : a priori, je te fais confiance.
    Mais ça m'intéresse de savoir où tu as trouvé cette information.
    Je suppose que ca doit se trouver dans les spécifications du langage, mais en cherchant vite fait je n'ai pas trouvé...

    Mais on peut vérifier cela facilement avec un petit bout de code :
    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public class Main {
     
        public static void main(String[] args) {
            new Main().test();
        }
     
        public void test() {
     
            class Inner1 {
                public String toString() {
                    return "Hello";
                };
            }
     
            final String localvar;
            localvar = "World";
     
            class Inner2 {
                public String toString() {
                    return localvar;
                }
            }
     
     
            for (Constructor<?> c : Inner1.class.getDeclaredConstructors()) {
                System.out.println( c );
            }
     
            System.out.println();
     
            for (Constructor<?> c : Inner2.class.getDeclaredConstructors()) {
                System.out.println( c );
            }
        }
    };

    Citation Envoyé par Feriaman Voir le message
    Au contraire : dans la question 6b, l'initialisation de la variable statique j a visiblement lieu avant le constructeur de "Derived", alors que la règle dit qu'il devrait avoir lieu après.
    Non pas tout à fait. Les bloc static sont initialisé lors du chargement de la classe.


    Citation Envoyé par Feriaman Voir le message
    J'en déduis que les variables statiques sont initialisées différemment des variables non-statiques (ce qui est confirmé par la règle puisqu'elles ont lieu avant).
    Les variables static sont initialisé au chargement de la classe.
    Les variables d'instances sont initialisé pendant l'appel du constructeur, juste après l'appel du constructeur parent.

    En fait cela revient à faire quelque chose comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        int i;
        public Derived() {
            super();
            i = 4;
        }
    Cela montre juste qu'il faut éviter d'utiliser une méthode virtuelle dans un constructeur, cas avec l'héritage on peut se retrouver à manipuler des variables d'instances indéfinies...



    Citation Envoyé par Feriaman Voir le message
    Une des raisons que j'imagine (et là tu as raison, il ne s'agit que de mon imagination), c'est qu'elles sont pré-initialisées avant le lancement du programme. Et elles sont pré-initialisées parce qu'elles ne sont pas rangées au même endroit que les autres en mémoire.
    Les variables static/d'instances sont implicitement initialisées avec 0/null/false (selon le cas).
    Les variables locales doivent obligatoirement être initialisé avant d'être utilisées, sous peine d'erreur de compilation.


    Citation Envoyé par Feriaman Voir le message
    Je ne comprends pas cet argument.
    Java prévoit cette solution pour gérer ce besoin.
    Pour moi la question ne se pose pas : si j'ai ce besoin j'utilise cette solution.
    Mais le besoin est quasi inexistant


    a++

  20. #20
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 565
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 565
    Points : 21 630
    Points
    21 630
    Par défaut
    Citation Envoyé par Feriaman Voir le message
    Tu l'affirmes, et encore une fois : a priori, je te fais confiance.
    Mais ça m'intéresse de savoir où tu as trouvé cette information.
    Je suppose que ca doit se trouver dans les spécifications du langage, mais en cherchant vite fait je n'ai pas trouvé...
    À mon avis c'est plus compliqué que ça.
    En imposant que ces variables soient finales, les JLS imposent que tout se passe comme si elles étaient passées par copie implicite dans un bloc implicite d'initialisation.

    Comment ça fonctionne exactement ne nous regarde pas, mais l'idée du passage par copie semble "la plus simple."

    Il faut se rappeler que les variables locales ne "sont" nulle part en particulier. On pourrait penser qu'elles sont dans la stack, mais pas forcément : certaines peuvent être dans un registre, ou carrément inutilisées. Même quand elles sont dans la stack, la stack a une durée de vie qui peut être inférieure à l'instance d'objet créée.

    De même, elles ne peuvent pas être partagées entre plusieurs instances d'inner class, parce que ces instances n'ont pas toutes la même durée de vie, et qu'on ne va pas compter des références pour ce genre d'économies de bouts de ficelle.

    La question : est-ce que d'autres gens l'utilise beaucoup ou pas beaucoup n'a rien à voir là-dedans.
    La bonne pratique n'est pas un concours de popularité.
    On pourrait arguer que si.
    La bonne pratique n'est pas une fin en soi, elle sert une fin.
    Assez souvent, il s'agit d'être maintenable, par exemple en se relisant facilement et en pouvant être repris par beaucoup de gens. L'utilisation de syntaxes bien connues aide beaucoup.

Discussions similaires

  1. Serialization et classe anonyme
    Par vincent63 dans le forum Langage
    Réponses: 6
    Dernier message: 07/07/2006, 19h03
  2. Variable d'instance et classe anonyme
    Par zoullou dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 21/05/2006, 12h30
  3. [Débutant]Passer une classe abstraite en paramètre
    Par Invité dans le forum Débuter
    Réponses: 2
    Dernier message: 06/01/2006, 17h56
  4. Réponses: 5
    Dernier message: 16/08/2005, 10h30
  5. [classe anonyme] implementant une interface
    Par stanilas dans le forum Langage
    Réponses: 4
    Dernier message: 30/11/2004, 00h18

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