Ответ 1
Первый ответ в основном правильный - protected
доступ к элементам осуществляется
- классы из одного пакета
- подклассы класса объявления из других пакетов
Однако есть небольшой трюк:
6.6.2 Сведения о защищенном доступе
Защищенный член или конструктор объекта может быть доступен извне пакета, в котором он объявляется только кодом, ответственным за реализацию этого объекта.
Это означает, что подкласс из другого пакета не может получить доступ к protected
членам произвольных экземпляров своих суперклассов, они могут обращаться к ним только в экземплярах своего собственного типа (где type - это тип выражения типа компиляции, поскольку он компилируется проверка времени).
Например (предполагая, что этот код находится в Cat
):
Dog dog = new Dog();
Animal cat = new Cat();
dog.testInstanceMethod(); // Not allowed, because Cat should not be able to access protected members of Dog
cat.testInstanceMethod(); // Not allowed, because compiler doesn't know that runtime type of cat is Cat
((Cat) cat).testInstanceMethod(); // Allowed
Это имеет смысл, поскольку доступ к protected
членам Dog
на Cat
может привести к поломке инвариантов Dog
, тогда как Cat
может безопасно получить доступ к своим protected
членам, поскольку он знает, как обеспечить его собственные инварианты.
Подробные правила:
6.6.2.1 Доступ к защищенному члену
Пусть C - класс, в котором объявлен защищенный член m. Доступ разрешен только внутри тела подкласса S of C. Кроме того, если Id обозначает поле экземпляра или метод экземпляра, то:
- Если доступ осуществляется по квалифицированному имени Q.Id, где Q - имя ExpressionName, то доступ разрешен тогда и только тогда, когда тип выражения Q является S или подклассом S.
- Если доступ осуществляется с помощью выражения доступа к полю E.Id, где E является первичным выражением или выражением вызова метода E.Id(...), где E является первичным выражением, доступ разрешен тогда и только тогда, когда тип E является S или подклассом S.
6.6.2.2 Квалифицированный доступ к защищенному конструктору
Пусть C - класс, в котором объявлен защищенный конструктор, и пусть S - самый внутренний класс, в объявлении которого используется использование защищенного конструктора. Тогда:
- Если доступ осуществляется вызовом конструктора суперкласса super (...) или квалифицированным конструктором конструктора суперкласса формы E.super(...), где E является первичным выражением, тогда доступ разрешен.
- Если доступ является выражением создания экземпляра анонимного класса формы new C (...) {...} или выражением для экземпляра квалифицированного экземпляра класса E.new C (...) {...}, где E - первичное выражение, доступ разрешен.
- В противном случае, если доступ осуществляется с помощью простого экземпляра экземпляра экземпляра экземпляра формы new C (...) или выражения выражения экземпляра квалифицированного класса формы E.new C (...), где E Первичное выражение, тогда доступ не разрешен. Доступ к защищенному конструктору можно получить с помощью выражения создания экземпляра класса (которое не объявляет анонимный класс) только из пакета, в котором он определен.
См. также: