Visibilité des constructeurs privés Java

J'essaie de comprendre pourquoi il y a une différence entre l'accessibilité des membres de la classe en parlant de 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
    }
  }
}

Les membres privés de A, comme étant privés, ne devraient pas être accessibles à partir de 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éterminer L'accessibilité), on peut lire:

[...]

Membre (classe, interface, champ, ou méthode) d'un type de référence, ou un constructeur d'un type de classe, est accessible uniquement 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, et l'accès est autorisé si et seulement si cela se produit dans le corps de la classe de niveau supérieur (§7.6) qui entoure 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ée private?

31
demandé sur Adam 2015-11-19 12:50:01

3 réponses

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

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

Notez que vous pouvez redéfinir une nouvelle méthode foo dans C, mais cette méthode ne permet pas de remplacer B.foo().

25
répondu WilQu 2015-11-19 10:03:46

Donc, l'astuce ici pourrait être la suivante :

Vous ne pouvez pas accéder à foo car il est déclaré privé, donc vous ne l'héritez pas en C.

Cependant, comme indiqué dans les commentaires, vous pouvez accéder à super.foo(); Car super fait référence à un type déclaré dans la même classe de niveau supérieur (voir JLS 6.6.1 pour cela).

Alors l'astuce est que l'appel super(s) peut être considéré comme appelant {[4] } qui finit par être le même cas que super.foo()

3
répondu benzonico 2015-11-19 10:17:40

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

Pour les constructeurs, les constructeurs ne sont jamais hérités. En outre, 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 L'erreur de compilation: Vehicle () a un accès privé dans Vehicle super(); ^ Ce qui indique clairement qu'un constructeur privé ne peut pas être accessible en utilisant super. Si nous sommes en mesure d'initialisation ou d'accéder à un constructeur privé, alors qu'est-ce le point dans la création d'un constructeur privé.

-2
répondu Ashish Ani 2015-11-19 10:29:33