31 votes

Visibilité des constructeurs privés de Java

J'essaie de comprendre pourquoi il y a une différence entre l'accessibilité des membres de la classe et les constructeurs.

Prenons l'exemple suivant :

class A {
  static class B {  
    private B(String s) {}
    private void foo() {}
  }
  static class C extends B {
    public C(String s) {
      super(s); // call B(String), which is private, and obviously accessible
    }
    void bar() {
      foo(); // compilation error (symbol unknown), as B.foo() is private
    }
  }
}

Membres privés de A étant privés, ils ne devraient pas être accessibles à partir de l'Internet. B . Pour les champs et les méthodes, c'est le cas, mais il semble que les constructeurs ne suivent pas la même règle.

Du JLS-8 ( 6.6.1. Détermination de l'accessibilité ), on peut lire :

[...]

Un membre (classe, interface, champ ou méthode) d'un type de référence, ou un constructeur d'un type de classe, n'est accessible que si le type est accessible et que le membre ou le constructeur est déclaré pour permettre l'accès :

  • [...]

  • Sinon, le membre ou le constructeur est déclaré private L'accès est autorisé si et seulement si il a lieu dans le corps de la classe de niveau supérieur (§7.6) qui contient la déclaration du membre ou du constructeur.

Quelqu'un peut-il m'expliquer pourquoi le constructeur est accessible à partir de C même en étant déclaré private ?

25voto

WilQu Points 3010

La méthode foo() est privée, donc vous n'en héritez pas et vous ne pouvez pas l'appeler directement à partir de l'interface utilisateur. C classe.

Cependant, vous pouvez voir les méthodes privées et le constructeur de l'application. B puisque tout est déclaré dans la même classe contenante, et y accéder avec super c'est pourquoi super() fonctionne. De la même manière, vous pouvez accéder foo con super.foo() .

Notez que vous pouvez redéfinir une nouvelle méthode foo en C mais cette méthode ne remplacera pas B.foo() .

3voto

benzonico Points 3082

Le truc ici pourrait être le suivant :

vous ne pouvez pas accéder foo parce qu'il est déclaré privé et qu'on n'en hérite pas en C.

Cependant, comme il a été noté dans les commentaires, vous pouvez accéder à super.foo(); parce que super fait référence à un type qui est déclaré dans la même classe de premier niveau (voir JLS 6.6.1 à ce sujet).

Alors l'astuce consiste à appeler super(s) peut être considéré comme un appel super.<init>(s) ce qui revient à dire que c'est le même cas que super.foo()

-2voto

Ashish Ani Points 210

La méthode Foo() n'est pas accessible dans la classe C, car la méthode foo() est privée et une méthode privée ne peut pas être héritée par la classe de base.

Pour les constructeurs, les CONSTRUCTORS NE SONT JAMAIS INHERES. Aussi, j'ai compilé ce code :

 class Vehicle{  
        int speed=50;  
        private Vehicle()
        {
           System.out.println("Private Vehicle constructor");
        }
    } 
    public class Bike4 extends Vehicle{  
        int speed=100;   
    Bike4()
    {
        super();
         System.out.println("Hi I n constructor");
    }
  void display(){  
   System.out.println(super.speed);//will print speed of Vehicle now  
  }  
  public static void main(String args[]){  
   Bike4 b=new Bike4();  
   b.display();  

}  
}  

Et obtenir une erreur de compilation : Vehicle() has private access in Vehicle super() ; ^ Ce qui indique clairement qu'on ne peut pas accéder à un constructeur privé en utilisant super. Si nous sommes capables d'initialiser ou d'accéder à un constructeur privé, alors quel est l'intérêt de créer un constructeur privé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X