Что-то я стала сомневаться по поводу двух модификаторов доступа: protected и default. И решила написать статью, чтобы освежить знания. В основном приходится сталкиваться с private и public.
В Java определены 4 модификатора доступа:
Понимание protected-модификатора доступа
Понимание default-модификатора (пакетный доступ) доступа
Члены класса, объявленные без явного указания модификатора доступа, определены с пакетным доступом. Они доступны только классам и интерфейсам объявленным в одном и том же пакете.
В Java определены 4 модификатора доступа:
- public (наименее ограничивающий доступ) (UML обозначение - "+")
- protected (UML обозначение - "#")
- default
- private (наиболее ограничивающий доступ) (UML обозначение - "-")
Понимание public-модификатора доступа
Public классы и интерфейсы доступны из всех пакетов, в производных и непроизводных (несвязанных) классах.
Таблица получения доступа к public классу и его членам
Понимание protected-модификатора доступа
Члены класса, объявленного с модификатором доступа protected, доступны из:
- Классы и интерфейсы, объявленные в том же пакете.
- Все производные классы, даже если они определены в различных пакетах.
Но есть тут один скользкий момент
Рассмотрим на примере (здесь оба класса расположены в пакете by.modifier):
package by.modifier;
public class ModifierTest extends PrivateModifier{
public static void main(String[] args){
new ModifierTest().modifierTest();
}
public void modifierTest(){
System.out.println("Test 1 " + getHello());
PrivateModifier privateModifier = new PrivateModifier();
System.out.println("Protected test " + privateModifier.getHello());
}
}
В данном примере все хорошо, компиляция пройдет успешно
Test 1 hello Protected test hello
С одной стороны похожий пример, но совершенно другой на самом деле (здесь ModifierTest находится в default package (здесь имеет значение только то, что это другой пакет)). То есть родитель-класс и наследник находятся в разных пакетах.
import by.modifier.PrivateModifier;
public class ModifierTest extends PrivateModifier{
public static void main(String[] args){
new ModifierTest().modifierTest();
}
public void modifierTest(){
System.out.println("Test 1 " + getHello());
PrivateModifier privateModifier = new PrivateModifier();
System.out.println("Protected test " + privateModifier.getHello());
}
}
Так вот здесь мы получим интересную ошибку
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method getHello() from the type PrivateModifier is not visible
at ModifierTest.modifierTest(ModifierTest.java:15)
at ModifierTest.main(ModifierTest.java:8)
Ошибка произошла из-за попытки доступа к protected методу класса наследника, который находится в другом пакете, через создание нового ссылочного объекта родителя.
Кратко сформулируем:
Класс-наследник может наследовать и получать доступ к protected-членам своего родительского класса, несмотря на то, в каком пакете он определен.
Производный класс в отличном пакете от пакета, в котором находится родительский класс, не может получать доступ к protected-переменным родительского класса, используя ссылочную переменную на родителя(новый объект-родитель).
Понимание default-модификатора (пакетный доступ) доступа
Члены класса, объявленные без явного указания модификатора доступа, определены с пакетным доступом. Они доступны только классам и интерфейсам объявленным в одном и том же пакете.
Подсказка
Модификатор доступа по умолчанию можно сравнить с уровнем доступа на уровне пакета (доступ только внутри пакета), а protected (защищенный доступ) можно сравнить с уровнем доступа на уровне пакета + "наследники". Наследники могут иметь доступ только, используя наследование, а не ссылку (доступ к членам класса используя оператор "." на объекте).
Понимание private-модификатора
Это самый строгий модификатор доступа. Члены класса, объявленные с модификатором private доступны только из него самого.
Модификатор доступа по умолчанию можно сравнить с уровнем доступа на уровне пакета (доступ только внутри пакета), а protected (защищенный доступ) можно сравнить с уровнем доступа на уровне пакета + "наследники". Наследники могут иметь доступ только, используя наследование, а не ссылку (доступ к членам класса используя оператор "." на объекте).
Понимание private-модификатора
Это самый строгий модификатор доступа. Члены класса, объявленные с модификатором private доступны только из него самого.