Понимание защищенного Java-модификатора
У меня есть class под названием A в пакете 1 и другой class C в пакете2. Класс C расширяет class A.
A имеет переменную экземпляра, которая объявляется следующим образом:
protected int protectedInt = 1;
Вот код для classа A
- Создание экземпляра универсального classа в Java
- Parse Date from String в этом формате: dd / MM / yyyy
- Самый быстрый способ сортировки 3 значений в Java
- Почему Java-код с внутренним classом генерирует третий файл SomeClass $ 1.class?
- Разделить строку на каждую третью запятую в Java
package package1; public class A { public int publicInt = 1; private int privateInt = 1; int defaultInt = 1; protected int protectedInt = 1; }
И вот код для classа C:
package package2; import package1.A; public class C extends A{ public void go(){ //remember the import statement A a = new A(); System.out.println(a.publicInt); System.out.println(a.protectedInt); } }
Eclipse подчеркивает последнюю строку в C.go () и говорит, что «A.protectedInt» не отображается. Похоже, что это противоречит определению ключевого слова «protected», приведенному в документации о oracle.
Защищенный модификатор указывает, что к члену можно получить доступ только в своем собственном пакете (как и в пакете private) и, кроме того, подclassе его classа в другом пакете.
Что тут происходит?
- Что такое class java pojo, java bean, обычный class?
- Отражающие вращения и изображения
- Закрыть сканер без закрытия System.in
- На каком языке написана компилятор Java и JVM?
- Конфигурация XML-схемы Spring: с версией или без нее?
- Формат Java 8 LocalDate Jackson
- Параметр JSON весной MVC-controller
- Встраивание ресурсов (изображений, звуковых fragmentов и т. Д.) В проект Java, затем использование этих ресурсов
Что тут происходит?
Вы неправильно поняли смысл protected
. Вы можете получить доступ к защищенным членам, объявленным в A
из C
, но только для экземпляров C
или подclassов C
Информацию о защищенном доступе см. В разделе 6.6.2 JLS . В частности:
Пусть C – class, в котором объявлен защищенный член. Доступ разрешен только внутри тела подclassа S C.
Кроме того, если Id обозначает поле экземпляра или метод экземпляра, то:
[…]
Если доступ осуществляется с помощью выражения доступа к полю E.Id, где E является первичным выражением или выражением вызова метода E.Id (…), где E является первичным выражением, тогда доступ разрешен только в том случае, если и только если тип E является S или подclassом S.
(Акцент мой.)
Так что этот код будет в порядке:
C c = new C(); System.out.println(c.publicInt); System.out.println(c.protectedInt);
Так как C
наследует A
, C
может непосредственно использовать protected
переменную A
как показано ниже
public class C extends A{ public void go(){ System.out.println(protectedInt); } }
В соответствии с вашим кодом вы создаете экземпляр A
и получаете доступ к protected
переменной через этот экземпляр , что нарушает правило java. Защищенная переменная не видна вне пакета
public void go(){ //remember the import statement A a = new A(); System.out.println(a.publicInt); System.out.println(a.protectedInt); }
Когда вы делаете A a = new A();
и a.protectedInt
вы пытаетесь получить доступ к защищенному члену A, который является незаконным в соответствии со стандартами java
Вместо этого вы можете сделать this.protectedInt
напрямую.
Нет необходимости создавать экземпляр classа защиты внутри classа Protection2. Вы можете напрямую вызвать защищенную переменную без создания экземпляра classа защиты. Поскольку class Protection2 расширяет class защиты. Таким образом, переменная автоматически унаследована подclassом.
Попробуйте использовать код ниже:
public class Protection2 extends Protection{ Protection2() {System.out.println("n_pro = " +n_pro); }}
В том же пакете, где объявлен защищенный член, разрешен доступ:
package package1; public class C extends A{ public void go(){ A a = new A(); System.out.println(a.protectedInt); // got printed C c = new C(); System.out.println(c.protectedInt); // got printed as well } }
Вне пакета, в котором объявлен защищенный член, доступ разрешен только в том случае, если по коду, ответственному за реализацию этого объекта. В этом случае C отвечает за реализацию этого объекта, поэтому он может получить доступ к защищенному.
package package2; public class C extends A{ public void go(){ A a = new A(); System.out.println(a.protectedInt); // compiler complains C c = new C(); System.out.println(c.protectedInt); // got printed } }
Защищенные средства:
a) Этот член будет доступен для всех classов в одном пакете с помощью ссылки на объект.
b) Для другого пакета это будет доступно только внутри подclassов A say B, а используемая ссылка может быть экземпляра B или любого подclassа B.
Приведем пример:
Пусть A – родительский class в некотором пакете say com.ex1
Пусть B, C – classы в разных пакетах по com.ex2
say say com.ex2
. Кроме того, B extends A
и C extends B
Мы увидим, как мы можем использовать защищенное поле A внутри B (подclass A)
Код А:
public class A { protected int a = 10; }
Код B:
public class B extends A { public void printUsingInheritance() { // Using this System.out.println(this.a); } public void printUsingInstantiation() { // Using instance of B B b = new B(); System.out.println(ba); // Using instance of C as C is subclass of B C c = new C(); System.out.println(ca); A a = new A(); System.out.println(aa); // Compilation error as A is not subclass of B } }
Код C:
public class C extends B { }
Для защищенных статических :
Те же правила применяются, за исключением того, что в b) теперь он доступен в любом подclassе classа A по ссылке classа A. Справка