Модификаторы доступа определяет, какие классы могут обращаться к данному классу и его полям, конструкторам и методам. Могут быть указаны отдельно для класса, его конструкторов, полей и методов и иметь один из четырех различных модификаторов:
- Private;
- default;
- protected;
- public.
Следующая таблица суммирует, к каким конструкциям Java может применяться каждый модификатор:
| private | default | protected | public | |
|---|---|---|---|---|
| Класс | No | Yes | No | Yes |
| Вложенный класс | Yes | Yes | Yes | Yes |
| Конструктор | Yes | Yes | Yes | Yes |
| Метод | Yes | Yes | Yes | Yes |
| Поля | Yes | Yes | Yes | Yes |
Private
Если метод или переменная помечены как private (им назначен модификатор частного доступа), то только код внутри того же класса может получить доступ к переменной или вызвать метод. Код внутри подклассов не может получить доступ к переменной или методу, равно как и код из любого внешнего класса.
Классы не могут быть помечены таким модификатором. Подобная пометка класса будет означать, что никакой другой класс не сможет получить к нему доступ, а это означает, что вы вообще не сможете использовать его.
Вот пример назначения к полю:
public class Clock {
private long time = 0;
}
Переменная — long time была помечена как частная. Это означает, что переменная long time внутри класса Clock недоступна из кода вне него.
Доступ к частным полям
Поля часто объявляются частными для контроля доступа к ним из внешнего мира. В некоторых случаях поля являются действительно закрытыми, то есть они используются только внутри класса. В других случаях к полям можно получить доступ через методы доступа (например, геттеры и сеттеры). Вот пример:
public class Clock {
private long time = 0;
public long getTime() {
return this.time;
}
public void setTime(long theTime) {
this.time = theTime;
}
}
В приведенном выше примере два метода getTime() и setTime() могут получить доступ к переменной long time. Два метода объявлены как публичные, то есть они могут быть вызваны из кода в любом месте вашего приложения.
Частные конструкторы
Если конструктору в классе назначен частный модификатор, это означает, что конструктор не может быть вызван из-за пределов класса. Закрытый конструктор все еще может вызываться из других конструкторов или из статических методов того же класса:
public class Clock {
private long time = 0;
private Clock(long time) {
this.time = time;
}
public Clock(long time, long timeOffset) {
this(time);
this.time += timeOffset;
}
public static Clock newClock() {
return new Clock(System.currentTimeMillis());
}
}
Эта версия класса Clock содержит приватный конструктор и публичный конструктор. Закрытый конструктор вызывается из публичного (оператор this();). Он также вызывается из статического метода newClock().
Приведенный выше пример служит только для того, чтобы показать вам, что закрытый конструктор можно вызывать из открытых и из статических методов внутри одного и того же класса.
Default
Объявляется без записи модификатора доступа вообще. Означает, что код внутри самого класса, а также код внутри классов в том же пакете, что и этот класс, могут обращаться к классу, полю, конструктору или методу, которому назначен такой модификатор. Поэтому эту разновидность также иногда называют модификатором доступа к пакету.
Подклассы не могут получить доступ к методам и переменным-членам (полям) в суперклассе, если эти методы и поля помечены этим модификатором, если только подкласс не находится в том же пакете, что и суперкласс.
Вот пример:
public class Clock {
long time = 0;
}
public class ClockReader {
Clock clock = new Clock();
public long readClock{
return clock.time;
}
}
Поле времени в классе Clock не имеет модификатора, что означает, что ему неявно назначен по умолчанию. Следовательно, класс ClockReader может считывать переменную-член time объекта Clock при условии, что ClockReader и Clock находятся в одном и том же пакете Java.
Protected
Обеспечивает тот же доступ, что и модификатор по умолчанию, кроме того, подклассы могут обращаться к защищенным методам и переменным (полям) членов суперкласса. Это верно, даже если подкласс не находится в том же пакете, что и суперкласс.
Вот пример:
public class Clock {
protected long time = 0; // time in milliseconds
}
public class SmartClock() extends Clock{
public long getTimeInSeconds() {
return this.time / 1000;
}
}
В вышеприведенном примере у подкласса SmartClock есть метод getTimeInSeconds(), который обращается к переменной времени Clock суперкласса. Это возможно, даже если Clock и SmartClock не находятся в одном и том же пакете, поскольку поле времени помечено соответствующим модификатором.
Public
Общедоступный модификатор означает, что весь код может получить доступ к классу, полю, конструктору или методу независимо от того, где находится код доступа (в другом классе и в другом пакете):
public class Clock {
public long time = 0;
}
public class ClockReader {
Clock clock = new Clock();
public long readClock{
return clock.time;
}
}
Поле времени в классе Clock помечено общедоступным модификатором. Поэтому класс ClockReader может обращаться к полю времени в Clock независимо от того, в каком пакете находится ClockReader.
Доступ к классу
Важно помнить, что модификатор, назначенный классу, имеет приоритет над любыми модификаторами, назначенными полям, конструкторам и методам этого класса. Если класс помечен модификатором по умолчанию, то никакой другой класс вне того же пакета не может получить доступ к этому классу, включая его конструкторы, поля и методы. Это не поможет, если вы объявите эти поля общедоступными.
Частные и защищенные модификаторы не могут быть назначены классу. Только для конструкторов, методов и полей внутри классов. Классам могут быть назначены только по умолчанию (пакет) и общедоступный.
К интерфейсу
Java-интерфейсы предназначены для указания общедоступных полей и методов в классах, которые они реализуют. Поэтому вы не можете использовать модификаторы частного и защищенного доступа в них. Поля и методы в интерфейсах неявно объявляются общедоступными, если вы пропустите модификатор, поэтому вы также не можете использовать модификатор по умолчанию (без него).
Модификаторы и наследование
Когда вы создаете подкласс некоторого класса, у методов в подклассе не может быть назначено им менее доступных модификаторов, чем в суперклассе.
Например, если метод в суперклассе является общедоступным, то он также должен быть таким в подклассе, в случае, если подкласс переопределяет метод. Если метод в суперклассе защищен, то он должен быть защищенным или общедоступным в подклассе.
Хотя не разрешено уменьшать доступность переопределенного метода, разрешено расширять доступность переопределенного метода. Например, если методу назначен модификатор по умолчанию в суперклассе, то разрешается назначать переопределенный метод в подклассе модификатору открытого доступа.
