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 :

Accessibilité classe interne à une méthode


Sujet :

Langage Java

  1. #1
    Membre actif
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

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

    Informations forums :
    Inscription : Septembre 2011
    Messages : 196
    Points : 242
    Points
    242
    Par défaut Accessibilité classe interne à une méthode
    Bonjour,

    Voici le petit bout de code suivant :

    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
     
    public class InnerMethod {
     
    	private int x = 10;
     
    	public void test() {
    		class LocalClass {
    			private int x = 3;
     
    			private void printX() {
    				System.out.println(InnerMethod.this.x + this.x);
    			}
    		}
     
    		LocalClass l = new LocalClass();
    		l.printX();
    	}
     
    	public static void main(String[] args) {
    		InnerMethod monInnerMethod = new InnerMethod();
    		monInnerMethod.test();
    	}
     
    }
    Lorsque je lance ce programme, j'obtiens le résultat attendu : 13.

    Cependant je n'arrive pas à comprendre pourquoi j'ai le droit d'appeler l'instruction l.printX() étant donné que cette méthode est déclarée private au sein de la classe LocalClass.

    Ne devrais-je pas pouvoir l'appeler uniquement au sein de la classe LocalClass ??

  2. #2
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Alors déjà, remarquons qu'on peut trouver un exemple plus simple :

    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
    public class InnerMethod {
     
      private int x = 10;
     
      private class InnerClass {
        private int x = 3;
     
        private void printX() {
          System.out.println(InnerMethod.this.x + this.x);
        }
      }
     
     
      public void test() {
        InnerClass i = new InnerClass();
        i.printX();
      }
     
      public static void main(String[] args) {
        InnerMethod monInnerMethod = new InnerMethod();
        monInnerMethod.test();
      }
     
    }
    Parce que bon, les classes locales, c'est pas ce qu'on utilise le plus souvent, ce qui est normal vu que ça ne sert pas à grand-chose.

    Mais bon, donc, dans les classes internes : même raisonnement, même résultat. En fait, c'est le cas avec toutes les classes imbriquées. Pourquoi ?

    Eh bien on dit souvent que private restreint l'accès à la classe en cours, parce que c'est simple et que c'est l'idée de la chose.
    Mais en réalité c'est plus compliqué.

    Définition de l'accès private dans les JLS.

    En fait, private restreint l'accès non pas à la classe en cours, mais à la top-level class en cours.
    Une top-level class est une classe qui n'est imbriquée dans aucune autre : elle n'est pas déclarée entre les accolades d'une autre classe.

    Tout dans une classe a donc accès à tout ce qu'elle contient, même à ce qui est private dans une de ses classes imbriquées. Et même ses autres classes imbriquées ont cet accès absolu les unes aux autres.

    On peut donc en déduire, que, pour les classes private (qui ne sont accessibles qu'à la top-level class en cours) et pour les classes locales (qui ne sont accessibles qu'à la méthode en cours,) ça ne sert à rien de donner des droits d'accès à ce qu'elles contiennent.
    Parce que tout ce qui a accès à ces classes, a aussi accès à tout leur contenu, quel que soit le droit d'accès indiqué.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre actif
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

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

    Informations forums :
    Inscription : Septembre 2011
    Messages : 196
    Points : 242
    Points
    242
    Par défaut
    ok merci pour cette réponse très claire !

  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
    Salut,

    Citation Envoyé par thelvin Voir le message
    Tout dans une classe a donc accès à tout ce qu'elle contient, même à ce qui est private dans une de ses classes imbriquées. Et même ses autres classes imbriquées ont cet accès absolu les unes aux autres.
    Juste pour compléter la réponse de thelvin : ce mécanisme d'accès au private est propre au langage Java mais il n'existe pas au niveau du bytecode de la JVM.

    En fait il est simuler via la génération implicite d'une méthode d'accès par le compilateur. On peut repérer ces méthodes via la reflection et le marqueur "synthetic" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	for (Method method : LocalClass.class.getDeclaredMethods()) {
    		System.out.println(method + " / " + method.isSynthetic());
    	}
    Ce qui donne dans notre cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    static void InnerMethod$1LocalClass.access$0(InnerMethod$1LocalClass) / true
    private void InnerMethod$1LocalClass.printX() / false
    La méthode access$0() est généré par le compilateur avec une visibilité "package", et permet l'appel à la méthode private. Elle doit ressembler à quelque chose comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	static void access$0(LocalClass thiz) {
    		thiz.printX();
    	}
    Le compilateur remplacera alors l'appel "l.printX()" par l'appel de cette méthode static...



    Bref : autant éviter les méthodes private dans ces cas là


    a++

  5. #5
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Ah, je me disais bien qu'il y avait un truc que je comprenais pas, mais je voulais pas entrer dans les arcanes du bytecode.

    Merci pour la précision.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

Discussions similaires

  1. NoClassDefFound pour une inner classe dans une méthode de la classe
    Par joel.drigo dans le forum Général Java
    Réponses: 4
    Dernier message: 19/07/2013, 14h40
  2. Réponses: 0
    Dernier message: 05/02/2013, 13h38
  3. obtenir le nom de la classe dans une méthode static
    Par einboubou dans le forum Débuter avec Java
    Réponses: 4
    Dernier message: 13/11/2009, 16h46
  4. Intégrer une class et une méthode
    Par Zombiman dans le forum Langage
    Réponses: 11
    Dernier message: 03/06/2009, 14h21
  5. Réponses: 5
    Dernier message: 01/02/2007, 13h14

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