1. Обзор
В языке программирования Java поля, конструкторы, методы и классы могут быть помечены модификаторами доступа. В этом руководстве мы рассмотрим защищенный
доступ.
2. Защищенное
ключевое слово
В то время как элементы, объявленные как частные
, доступны только классу, в котором они объявлены, защищенное ключевое
слово разрешает доступ из подклассов и членов того же пакета.
Используя защищенное
ключевое слово, мы принимаем решения о том, какие методы и поля следует считать внутренними элементами пакета или иерархии классов, а какие доступны для внешнего кода.
3. Объявление защищенных
полей, методов и конструкторов
Во-первых, давайте создадим `класс с именем
FirstClass , содержащий
защищенное` поле, метод и конструктор:
public class FirstClass {
protected String name;
protected FirstClass(String name) {
this.name = name;
}
protected String getName() {
return name;
}
}
В этом примере с помощью ключевого слова protected
мы предоставили доступ к этим полям классам в том же пакете, что и FirstClass
, и подклассам FirstClass
.
4. Доступ к защищенным
полям, методам и конструкторам
4.1. Из того же пакета
Теперь давайте посмотрим, как мы можем получить доступ к защищенным
полям, создав новый GenericClass
, объявленный в том же пакете, что и FirstClass
:
public class GenericClass {
public static void main(String[] args) {
FirstClass first = new FirstClass("random name");
System.out.println("FirstClass name is " + first.getName());
first.name = "new name";
}
}
Поскольку этот вызывающий класс находится в том же пакете, что и FirstClass,
ему разрешено видеть и взаимодействовать со всеми защищенными
полями, методами и конструкторами.
4.2. Из другого пакета
Давайте теперь попробуем взаимодействовать с этими полями из класса, объявленного в пакете, отличном от FirstClass
:
public class SecondGenericClass {
public static void main(String[] args) {
FirstClass first = new FirstClass("random name");
System.out.println("FirstClass name is "+ first.getName());
first.name = "new name";
}
}
Как мы видим, мы получаем ошибки компиляции :
The constructor FirstClass(String) is not visible
The method getName() from the type FirstClass is not visible
The field FirstClass.name is not visible
Именно этого мы и ожидали, используя защищенное
ключевое слово. Это связано с тем, что SecondGenericClass
не находится в том же пакете, что и FirstClass
, и не является его подклассом.
4.3. Из подкласса
Давайте теперь посмотрим, что происходит, когда мы объявляем класс, расширяющий FirstClass
, но объявленный в другом пакете :
public class SecondClass extends FirstClass {
public SecondClass(String name) {
super(name);
System.out.println("SecondClass name is " + this.getName());
this.name = "new name";
}
}
Как и ожидалось, мы можем получить доступ ко всем защищенным полям, методам и конструкторам. Это потому, что SecondClass
является подклассом FirstClass
.
5. защищенный
внутренний класс
В предыдущих примерах мы видели защищенные
поля, методы и конструкторы в действии. Есть еще один частный случай — защищенный
внутренний класс.
Давайте создадим этот пустой внутренний класс внутри нашего FirstClass
:
package com.foreach.core.modifiers;
public class FirstClass {
// ...
protected static class InnerClass {
}
}
Как мы видим, это статический внутренний класс, поэтому его можно создать извне экземпляра FirstClass
. Однако, поскольку он защищен
, мы можем создать его экземпляр только из кода в том же пакете, что и FirstClass
.
5.1. Из того же пакета
Чтобы проверить это, давайте отредактируем наш GenericClass
:
public class GenericClass {
public static void main(String[] args) {
// ...
FirstClass.InnerClass innerClass = new FirstClass.InnerClass();
}
}
Как мы видим, мы можем без проблем создать экземпляр InnerClass , потому что
GenericClass
находится в том же пакете, что и FirstClass
.
5.2. Из другого пакета
Давайте попробуем создать экземпляр InnerClass
из нашего SecondGenericClass
, который, как мы помним, находится вне пакета FirstClass :
public class SecondGenericClass {
public static void main(String[] args) {
// ...
FirstClass.InnerClass innerClass = new FirstClass.InnerClass();
}
}
Как и ожидалось, мы получаем ошибку компиляции :
The type FirstClass.InnerClass is not visible
5.3. Из подкласса
Попробуем сделать то же самое из нашего SecondClass
:
public class SecondClass extends FirstClass {
public SecondClass(String name) {
// ...
FirstClass.InnerClass innerClass = new FirstClass.InnerClass();
}
}
Мы ожидали, что с легкостью создадим экземпляр нашего InnerClass
. Однако и здесь мы получаем ошибку компиляции:
The constructor FirstClass.InnerClass() is not visible
Давайте посмотрим на наше объявление InnerClass
:
protected static class InnerClass {
}
Основная причина, по которой мы получаем эту ошибку, заключается в том, что конструктор по умолчанию защищенного
класса неявно защищен .
Кроме того, SecondClass
является подклассом FirstClass, но не является подклассом InnerClass
. Наконец, мы также объявили SecondClass
вне пакета FirstClass
.
По всем этим причинам SecondClass
не может получить доступ к защищенному конструктору
InnerClass
.
Если бы мы хотели решить эту проблему и позволить нашему SecondClass
создавать экземпляр объекта InnerClass
, мы могли бы явно объявить общедоступный конструктор :
protected static class InnerClass {
public InnerClass() {
}
}
Делая это, мы больше не получаем ошибку компиляции, и теперь мы можем создать экземпляр InnerClass
из SecondClass
.
6. Заключение
В этом кратком руководстве мы обсудили модификатор защищенного
доступа в Java. С его помощью мы можем обеспечить предоставление только необходимых данных и методов подклассам и классам в одном пакете.
Как всегда, код примера доступен на GitHub .