1. Общ преглед
В езика за програмиране Java полетата, конструкторите, методите и класовете могат да бъдат маркирани с модификатори на достъпа. В този урок ще разгледаме защитения достъп.
2. Защитената ключова дума
Докато елементите, декларирани като частни, могат да бъдат достъпни само от класа, в който са декларирани, защитената ключова дума позволява достъп от подкласове и членове на същия пакет.
Използвайки защитената ключова дума, ние вземаме решения за това кои методи и полета трябва да се считат за вътрешни елементи на йерархията на пакет или клас и кои са изложени на външен код.
3. Деклариране на защитени полета, методи и конструктори
Първо, нека създадем aклас с име FirstClass, съдържащ защитено поле, метод и конструктор:
public class FirstClass { protected String name; protected FirstClass(String name) { this.name = name; } protected String getName() { return name; } }
С този пример, като използваме защитената ключова дума, предоставихме достъп до тези полета на класове в същия пакет като 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.baeldung.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 { }
The main reason we are getting this error is that the default constructor of a protected class is implicitly protected. In addition, SecondClassis a sub-class of FirstClass but is not a sub-class of InnerClass. Finally, we also declaredSecondClass outside FirstClass' package.
For all these reasons, SecondClass can't access the protectedInnerClass constructor.
Ако искахме да разрешим този проблем и да позволим на SecondClass да създаде екземпляр на обект InnerClass , бихме могли изрично да декларираме публичен конструктор :
protected static class InnerClass { public InnerClass() { } }
Правейки това, вече не получаваме грешка при компилация и вече можем да създадем екземпляр на InnerClass от SecondClass .
6. Заключение
В този бърз урок обсъдихме модификатора на защитения достъп в Java. С него можем да гарантираме излагането само на необходимите данни и методи на подкласове и класове в същия пакет.
Както винаги, примерният код е достъпен в GitHub.