Подтвердить что ты не робот

Видимость частных конструкторов Java

Я пытаюсь понять, почему существует разница между доступностью членов класса, когда речь идет о конструкторах.

Рассмотрим следующий пример:

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
    }
  }
}

Частные члены A, как частные, не должны быть доступны из B. Для полей и методов это так, но кажется, что конструкторы не выполняют одно и то же правило.

Из JLS-8 (6.6.1. Определение доступности), мы можем прочитать:

[...]

Элемент (класс, интерфейс, поле или метод) ссылочного типа или конструктор типа класса доступен только в том случае, если тип доступен и член или конструктор объявлен для разрешения доступа:

  • [...]

  • В противном случае член или конструктор объявляется private, и доступ разрешен тогда и только тогда, когда он встречается внутри тела класса верхнего уровня (§7.6), который включает объявление члена или конструктора.

Может ли кто-нибудь объяснить мне, почему конструктор доступен из C, даже будучи объявленным private?

4b9b3361

Ответ 1

Метод foo() является закрытым, поэтому вы не наследуете его и не можете вызвать его непосредственно из класса C.

Однако вы можете видеть частные методы и конструктор из B, поскольку все объявлено в том же содержащем классе и доступ к ним с помощью super, поэтому работает super(). Таким же образом вы можете получить доступ к foo с помощью super.foo().

Обратите внимание, что вы можете переопределить новый метод foo в C, но этот метод не будет отменять B.foo().

Ответ 2

Таким образом, здесь может быть трюк:

вы не можете получить доступ к foo, потому что он объявлен приватным, поэтому вы не наследуете его в C.

Однако, как было отмечено в комментариях, вы можете получить доступ к super.foo();, потому что super относится к типу, объявленному в том же классе верхнего уровня (см. JLS 6.6.1 для этого).

Тогда фокус в том, что вызов super(s) можно рассматривать как вызывающий super.<init>(s), который заканчивается тем же случаем, что и super.foo()

Ответ 3

Метод Foo() недоступен в классе C, поскольку метод foo() является частным и приватным методом, который не может быть унаследован базовым классом.

Для конструкторов КОНСТРУКТОРЫ НИКОГДА НИКОГДА НЕ БУДУТ ВЕРНУТЬСЯ. Кроме того, я скомпилировал этот код:

 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();  

}  
}  

И получите ошибку времени компиляции: Vehicle() имеет личный доступ к транспортному средству       супер();       ^ Что явно указывает, что к закрытому конструктору нельзя получить доступ с помощью супер. Если мы можем инициализировать или получить доступ к частному конструктору, то какой смысл в создании частного конструктора.