Вступление
Модификаторы - это ключевые слова, которые позволяют нам точно настроить доступ к нашему классу и его членам, их область действия и поведение в определенных ситуациях. Например, мы можем контролировать, какие классы / объекты могут получить доступ к определенным членам нашего класса, может ли класс быть унаследованным или нет, можем ли мы переопределить метод позже, должны ли мы переопределить метод позже и т. Д.
Ключевые слова-модификаторы записываются перед типом и именем
переменной / метода / класса (возвращаемого значения), например
private int myVar
или public String toString()
.
Модификаторы в Java делятся на две группы - доступ и отсутствие доступа :
- Доступ:
public
,private
,protected
- Без доступа:
static
,final
,abstract
,synchronized
,volatile
,transient
иnative
Хотите узнать больше о модификаторах запрета доступа? Ознакомьтесь с нашей статьей « Модификаторы без доступа в Java» .
Модификаторы доступа
Модификаторы доступа работают с видимостью членов класса. Они контролируют, могут ли другие классы видеть или изменять определенные переменные / методы нашего класса.
Эти типы модификаторов тесно связаны с важной частью объектно-ориентированного программирования, называемой инкапсуляцией . Напоминаем, что инкапсуляция - это идея, которая связывает данные с кодом, который ими манипулирует. Контролируя доступ, вы можете предотвратить неправильное использование.
Например, убедившись, что к определенным переменным можно получить доступ только с помощью четко определенных методов (типичная комбинация методов get / set), мы гарантируем, что мы не встретим никаких неожиданных значений или не откажемся от внешнего доступа к определенным переменным / методам вообще .
Как упоминалось ранее, существует три модификатора доступа: public
,
private
и protected
. Java также обеспечивает контроль доступа по
умолчанию (когда не указан модификатор), который ведет себя аналогично
protected
.
public
- к члену можно получить доступ из любого местаprotected
- член недоступен только из неподклассов в другом пакете- по умолчанию (частный пакет) - также известный как
package
, член может быть доступен любому классу в том же пакете private
- член может быть доступен только другим членам в том же классе
В этой таблице показаны все возможные сценарии доступа для членов класса:
Частный По умолчанию Защищено Общественные
Тот же класс да да да да Подкласс (тот же пакет) Нет да да да Не подкласс (тот же пакет) Нет да да да Подкласс (другой пакет) Нет Нет да да Не подкласс (другой пакет) Нет Нет Нет да
Эта таблица применяется только к членам класса, а не к классам в целом.
Невложенный класс может быть только public
или без модификатора.
Поведение логично, когда класс объявлен без модификатора, к нему может
получить доступ только код в том же пакете, а когда он объявлен public
он также может использоваться в другом пакете.
Примечание . public
класс должен быть единственным (не вложенным)
классом в файле, и файл должен иметь то же имя, что и класс.
Например, скажем , у нас есть два пакета, творчески именованные
packageOne
и packageTwo
.
package packageOne;
public class MyPublicClass {
String noModifierText = "No Modifier";
private String privateText = "Private Text";
protected String protectedText = "Protected Text";
public String publicText = "Public Text";
public MyPublicClass() {
// We can access all members of a class from within that class
System.out.println("MyPublicClass constructor:")
System.out.println(noModifierText);
System.out.println(privateText);
System.out.println(protectedText);
System.out.println(publicText);
}
}
Обратите внимание, что приведенный выше код находится в файле с именем «MyPublicClass.java». Имя должно соответствовать классу, поскольку мы сделаем класс общедоступным, чтобы мы могли получить к нему доступ из другого пакета. То же самое относится и к другим классам, указанным ниже.
package packageOne;
class SamePackageExtends extends MyPublicClass {
public SamePackageExtends() {
System.out.println("SamePackageExtends constructor:")
System.out.println(noModifierText);
// Trying to access the private member privateText will fail, since private members
// can only be accessed by members of the same class, even though this class extends it.
// System.out.println(privateText);
System.out.println(protectedText);
System.out.println(publicText);
}
}
package packageOne;
class SamePackageDoesntExtend {
// Has the same access as SamePackageExtends
public SamePackageDoesntExtend() {
MyPublicClass myPublicClass = new MyPublicClass();
System.out.println("SamePackageDoesntExtend constructor:")
System.out.println(myPublicClass.noModifierText);
// System.out.println(myPublicClass.privateText);
System.out.println(myPublicClass.protectedText);
System.out.println(myPublicClass.publicText);
}
}
package packageTwo;
class DifferentPackageExtends extends packageOne.MyPublicClass {
public DifferentPackageExtends() {
System.out.println("DifferentPackageExtends constructor:")
// System.out.println(noModifierText); // Same class or same package only
// System.out.println(privateText); // Same class only
System.out.println(protectedText);
System.out.println(publicText);
}
}
package packageTwo;
class DifferentPackageDoesntExtend {
public DifferentPackageDoesntExtend() {
packageOne.MyPublicClass myPublicClass = new packageOne.MyPublicClass();
System.out.println("DifferentPackageDoesntExtend constructor:")
// System.out.println(myPublicClass.noModifierText);
// System.out.println(myPublicClass.privateText);
// System.out.println(myPublicClass.protectedText); // Same package only
System.out.println(myPublicClass.publicText);
}
}
Совет : Обычная практика - инкапсулировать класс. Это означает, что
мы объявляем переменные-члены как private
и объявляем public
методы,
которые ими управляют. Например, мы хотим позволить кому-то изменить
int ID
но мы также хотим убедиться, что int ID
является строго
положительным целым числом. Хотя это общедоступный метод, мы можем
сначала запустить проверку и манипулировать полем, если данное значение
проходит нашу проверку. Это конструкция, называемая set()
, и обычно
она сопровождается методом get()
(поскольку мы не можем читать частные
члены вне нашего класса) или когда мы хотим контролировать, как и когда
значение переменной может быть прочитанным.
class GetSetExample {
...
private int ID = 0; // Default value
public setID(int n) {
if (n > 0) {
ID = n;
}
else ID = 0;
}
public int getID() {
// Potential read conditions that need to be met
return ID;
}
...
}
Еще одна вещь, на которую следует обратить внимание, - это то, что
protected
- наименее используемый из всех модификаторов доступа. При
желании его можно легко обойти. Даже в другом пакете мы можем просто
унаследовать класс, к protected
членам которого мы хотим получить
доступ, а затем получить к ним доступ через этот унаследованный класс.
Имея это в виду, protected
чаще всего используется в качестве
руководства, которое гласит: «Этот член не предназначен для доступа не
подклассов в другом пакете», поэтому, хотя мы можем легко обойти
protected
контроль доступа, это не рекомендуется, поскольку Скорее
всего, это было не просто так.
Заключение
Модификаторы - это ключевые слова, которые позволяют нам точно настроить доступ к нашему классу и его членам, их область действия и поведение в определенных ситуациях. Они обеспечивают фундаментальные качества для наших классов и их членов. Каждый разработчик должен быть с ними внимательно ознакомлен, чтобы использовать их наилучшим образом.