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 :

[final]demande d'explication sur ce mot-clé


Sujet :

Langage Java

  1. #1
    Invité
    Invité(e)
    Par défaut [final]demande d'explication sur ce mot-clé
    Bonjour, je sais que le mot-clé final, sur une variable, fait que celle-ci ne sera jamais changée au cours de l'exécution.
    Mais je ne comprends pas exactement pourquoi je dois spécifier la variable suivante final pour la rendre accessible dans la (sous)classe suivante:
    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
     
     private void sortTable(ArrayList list, SMRPreferenceActionForm filter) {
     
     
            final int column = filter.getSortColumnNumber();  
     
            Collections.sort(list,
                    new AbstractSMRComparator(filter.getSortASC()) 
                    {
                          public int compare(Report o1, Report o2)
                          {
                              switch (column)
                              {
                                case 1 : ...
                                ...
                                default:return 0;
                              }
                          }
                    }
     
              );
        }
    Pouvez-vous me donner plus d'explication?
    Ps: Un peu déconcertant ce nouveau look. Je m'étais bien habitué à l'autre
    Dernière modification par Invité ; 18/04/2006 à 10h23.

  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,

    La variable doit être final car après la création de l'objet interne, il n'y a plus de "relation" entre la variable de la méthode et la celle de la classe interne. Il y a en effet deux copies de la même variable, et donc si entre temps on modifie une de ces variables, la seconde ne sera pas modifié.

    Le fait de n'authoriser que les variables final permet d'éviter des erreurs pas forcément évidente à comprendre si on tente de modifier les variables.

    Par exemple le code suivant qui tente de compter le nombre d'appel à la méthode compare ne peut pas marcher :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
            int count = 0;
     
            Collections.sort(list, new Comparator() {
                    public int compare(Object o1, Object o2) {
                        count++;
                        // ...
                        return x;
                    }
                });
    Tout comme celui ci qui modifie la valeur de la variable après la création de la classe interne :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
            Comparator c = new Comparator() {
                public int compare(Object o1, Object o2) {
                    switch (mode {
                        case 1:
                            ...
                        ...
                    }
                    // ...
                    return x;
                }
            };
     
            mode = 2;
            Collections.sort(list,c);
    Et final permet d'obtenir une erreur de compilation dans ces cas là, plutôt qu'un fonctionnement incorrect à l'exécution...

    Citation Envoyé par septentryon01
    Ps: Un peu déconcertant ce nouveau look. Je m'étais bien habituer à l'autre
    Il faut juste un peu de temps pour s'y faire...

    a++

  3. #3
    Invité
    Invité(e)
    Par défaut
    Merci pour ta réponse très complète!

    Cet example est donc bien une classe interne n'est-ce pas ?
    Il faut donc considérer la sous classe comme étant une 'nouveau' fichier java ?

    Mais je ne comprends toujours pas la différence entre mon example et celui-ci:
    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
    Toutefois, les membres statiques de la classe externe peuvent être hérités sans problème par la classe interne.
     Les classes imbriquées sont capables d'accéder à toutes les variables et méthodes de la classe parente, y compris celles déclarées avec un modificateur private.
    class ClasseParente { int x = 10; int y = 12; private int addition(){ return (x + y); } class ClasseInterne { void verification(){ if((x + y)== addition()) System.out.println("La classe interne a bien accédé " + "aux membres de sa classe parente."); } } public static void main(String[] args){ ClassParente obj_out = new ClasseParente(); ClasseInterne obj_in = obj_out.new ClasseInterne(); obj_in.verification(); } }
    Pourquoi parle-t-on de membres statiques ?
    Et pourquoi le mot-clé final n'entre-t-il pas toujours en considération ??
    Dernière modification par E.Bzz ; 08/04/2011 à 12h34.

  4. #4
    Membre régulier Avatar de Vesperal
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 81
    Points : 81
    Points
    81
    Par défaut
    En fait, ce qu'on appelle une classe interne est une seconde, ou n-ième classe définie à l'intérieur d'un même fichier java.

    Par éxemple, si tu as dans MonFichier.java :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    public class Classe1{ 
     ...
    A supprimer svp : fruit d'une erreur

  5. #5
    Membre régulier Avatar de Vesperal
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 81
    Points : 81
    Points
    81
    Par défaut
    En fait, ce qu'on appelle une classe interne est une seconde, ou n-ième classe définie à l'intérieur d'un même fichier java.

    Par éxemple, si tu as dans Classe1.java :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public class Classe1{ 
        ...
    }
    class Classe2{
        ...
    }
    class Classe3{
        ...
    }
    Les classes Classe2, et Classe3 sont des classes internes. Le fichier devra donc porter le nom de la première classe : Classe1.java

    Enfin plus éxactement de la seule classe étant définie avec le mot clef "public". Si tu avais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class Classe1{ 
        ...
    }
    public class Classe2{
        ...
    }
    class Classe3{
        ...
    }
    Il faudrait que ton fichier s'appelle "Classe2.java".
    A la compilation, le compilateur java va créer un fichier Classe2.class, et un fichier $1Classe1.class, et $2Classe3.class (ou quelque chose comme ca). Les classes ne seront accessible que depuis les classes définies dans ce fichier. C'est à dire que tu ne pourra faire un new Classe1() que dans le code du fichier Classe2.java par exemple.

    En ce qui concerne l'accès aux méthodes, les méthodes d'une classe sont accessibles depuis toutes les autres classes déifinies dans le même fichier. Et ce même si elles sont définies "privées".

    Tu peux faire par éxemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class Class1 {
        private String test1() {
             return test2();
        }
    }
    public Class2 {
        private String test2() {
             return "Test d'accès";
        }
    }
    Si tu apelles test1() de Classe1, ca te retournera "test d'accès";
    C'est comme si tu utilisais le mot clef "static", qui lui permet à une méthode ou une variable d'être accédée depuis n'importe quelle classe de n'importe quel fichier, sauf que là ca se retreint au fichier actuel. C'est le cas des méthodes main() de chaque programme java, qui sont définies en général comme suis :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    public static void main(String args[]) {
       ...
    }
    En ce qui concerne le mot clef "final", il permet de rendre non modifiable une variable ; définir une constante en fait. Essayer d'incrémenter une variable i définie comme suis par éxemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    final int i=0;
    ...
    this.i++; // retourne une erreur

  6. #6
    Invité
    Invité(e)
    Par défaut
    oui je sais ce qu'est une classe interne, je demande juste si mon example avec le new comparator se comporte de manière identique aux classes internes.
    Appraremment non si j'en crois au 2 eme example que j'ai cité.
    Dans mon example avec sortTable, je suis obligé de définir ma variable final.
    Or ce n'est pas le cas avec les classes internes ...
    Il y a qqch qui m'échape...
    Et en fait ceci me trouble :
    Citation Envoyé par adiGuba

    La variable doit être final car après la création de l'objet interne, il n'y a plus de "relation" entre la variable de la méthode et la celle de la classe interne.

  7. #7
    Membre régulier Avatar de Vesperal
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 81
    Points : 81
    Points
    81
    Par défaut
    Autant pour moi, j'avais mal compris le problème.

    La différence entre ton éxemple et le code que tu as donné est le fait que tu aies défini ta variable dans une méthode, et non dans une classe.

    Si tu avais mit ta variable column comme attribut de classe, il aurait été accessible depuis la classe interne.

    En fait, quand tu définis ta variable "final", elle est accessible comme si elle était devenue statique (sauf que tu ne peux pas faire de MaClasse.ma_variable) C'est à dire que depuis n'importe quelle sous classe ou méthode de la classe, tu peux y acceder. C'est compliqué à expliquer, mais ca revient à définir une variable dans le contexte, un peu comme si tu mettais un "global" en php.

  8. #8
    Invité
    Invité(e)
    Par défaut
    He ok je commence à comprendre.
    La différence vient du fait que l'attribut fait partie de la méthode et non de la classe elle-même ...
    Merci pour ton explication !

  9. #9
    Membre régulier Avatar de Vesperal
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 81
    Points : 81
    Points
    81
    Par défaut
    Si tu n'utilises pas de final, il faut que tu aies qqch comme :

    (si ta classe dans laquelle il y a sortTable() est "MaClasse")

    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
     
     
    ...
    private int column; // ou public, peu importe
    ...
     
     
    private void sortTable(ArrayList list, SMRPreferenceActionForm filter) {
     
     
            column = filter.getSortColumnNumber();  
     
            Collections.sort(list,
                    new AbstractSMRComparator(filter.getSortASC()) 
                    {
                          public int compare(Report o1, Report o2)
                          {
                              switch (MaClasse.this.column)
                              {
                                case 1 : ...
                                ...
                                default:return 0;
                              }
                          }
                    }
     
              );
        }

  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 septentryon01
    Cet example est donc bien une classe interne n'est-ce pas ?
    Oui... Il y a plusieurs types de classe interne :
    • Les classes internes "nommées". Il s'agit tout simplement de classe définit à l'intérieur d'une autre classe :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public class ClasseParente {
        class ClasseInterne {
            ...
        }
    }
    Cette classe sera compilé dans un fichier ClasseParente$ClasseInterne.class
    • Les classes internes anonymes. Il s'agit de classe dont l'implémentation est à la suite du constructeur, ce qui permet de redéfinir quelques unes de ses méthodes. En général ce type de classes est défini à l'intérieur d'une méthode (c'est ton premier exemple) :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class ClasseParente {
     
        public void method() {
     
            Object o = new Object() {
                public String toString() {
                    return "Hello World !";
                }
            };
     
            System.out.println( o ); // affiche "Hello World !";
        }
    }

    Citation Envoyé par septentryon01
    Mais je ne comprends toujours pas la différence entre mon example et celui-ci:

    Toutefois, les membres statiques de la classe externe peuvent être hérités sans problème par la classe interne.
    Les classes imbriquées sont capables d'accéder à toutes les variables et méthodes de la classe parente, y compris celles déclarées avec un modificateur private.
    Cela signifie simplement que les classes internes ont une visibilité sur les champs de la classes parentes, même ceux qui sont private ! Cela permet par exemple de faire des comparator qui manipulent des champs normalement protégé et innacessible...

    De plus les classes internes sont liée à l'instance de leurs classes parentes.

    Ainsi le code suivant compile parfaitement :
    Code java : 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
        public class ClasseParente {
     
            private String name = "World";
     
            public void method() {
     
                Object o = new Object() {
                    public String toString() {
                        return "Hello " + name;
                    }
                };
     
            }
     
            class ClasseInterne {
                public void method() {
                    System.out.println(name);
                }
            }
        }
    Et name référence bien le champs de la classe ClasseParente. On peut même utiliser la notation ClasseParente.this.name afin d'éviter d'éventuelle conflit...

    En fait chaque classe interne possède un lien implicite avec sa classe parente... C'est comme si tu avais rajouté un constructeur avec la référence de la classe parente (et c'est ce qui est fait par le compilateur).

    Citation Envoyé par septentryon01
    Pourquoi parle-t-on de membres statiques ?
    Euh... je ne vois pas de membres statiques... Tu veux peut-être parler de "classe static". Les classes internes statique ne sont pas lié à une instance de la classe parente. Elle sont donc un peu plus indépendante (le ClasseParente.this.name ne marchera pas), même si elles conservent la même visibilité sur les champs d'une autre instance de la classe parente (qu'elle peut recevoir en paramètre par exemple).

    Citation Envoyé par septentryon01
    Et pourquoi le mot-clé final n'entre-t-il pas toujours en considération ??
    Car ici c'est la référence même de la classe (this) qui est passé à la classe interne. Or this est déjà final puisqu'il ne peut pas être modifié...

    a++

  11. #11
    Invité
    Invité(e)
    Par défaut
    Ha oui effectivement cela fonctionne
    Un tout grand merci pour les infos. C'est clair maintenant!

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

Discussions similaires

  1. [filter2] Demande d'explication sur cette fonction
    Par ranell dans le forum Images
    Réponses: 3
    Dernier message: 10/05/2007, 09h19
  2. Demande d explication sur protocole FTP
    Par Mr_Chut dans le forum Réseau
    Réponses: 1
    Dernier message: 04/05/2007, 18h47
  3. Réponses: 4
    Dernier message: 09/10/2006, 22h12
  4. Réponses: 3
    Dernier message: 27/09/2006, 13h11
  5. [C#] demande d'explication sur un sample msdn
    Par legillou dans le forum Windows Forms
    Réponses: 2
    Dernier message: 27/06/2006, 17h01

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