Язык Java предоставляет множество модификаторов, которые в основном делятся на следующие две категории:
Модификаторы используются для определения классов, методов или переменных и обычно размещаются в начале инструкции. Проиллюстрируем это на следующем примере:
public class className { // ... } private boolean myFlag; static final double weeks = 9.5; protected static final int BOXWIDTH = 42; public static void main(String[] arguments) { // 方法体}
В Java элементы управления доступом могут использоваться для защиты доступа к классам, переменным, методам и конструкторам. Java поддерживает 4 различных права доступа.
Значение по умолчанию, также называемое значением по умолчанию, отображается в том же пакете и не использует никаких модификаторов.
Private, указанный с помощью модификатора Private, видимый в том же классе.
Public, указанный с помощью модификатора public, видимый всем классам.
Защищено, указано с модификатором protected, видимо для классов и всех подклассов в одном пакете.
Переменные и методы, объявленные с модификаторами доступа по умолчанию, видны классам в том же пакете. Переменные в интерфейсе неявно объявляются как public static final
, а методы в интерфейсе по умолчанию имеют права доступа public
.
Пример:
Как показано в следующем примере, переменные и методы можно объявлять без каких-либо модификаторов.
String version = "1.5.1"; boolean processOrder() { return true; }
Модификатор доступа Private — это наиболее ограничительный уровень доступа, поэтому методы, переменные и конструкторы, объявленные как частные, доступны только тому классу, которому они принадлежат, а классы и интерфейсы не могут быть объявлены как частные.
Переменные, объявленные как типы частного доступа, могут быть доступны внешним классам только через общедоступные методы получения в классе.
Использование модификатора доступа Private в основном используется для сокрытия деталей реализации класса и защиты данных класса.
Следующий класс использует модификатор частного доступа:
public class Logger { private String format; public String getFormat() { return this.format; } public void setFormat(String format) { this.format = format; } }
В этом примере переменная формата в классе Logger является частной переменной, поэтому другие классы не могут напрямую получать и устанавливать значение этой переменной. Чтобы другие классы могли работать с этой переменной, определены два public
метода: getFormat()
(возвращает значение формата) и setFormat(String)
(устанавливает значение формата).
Классы, методы, конструкторы и интерфейсы, объявленные как общедоступные, могут быть доступны любому другому классу.
Если несколько общедоступных классов, имеющих доступ друг к другу, распределены в разных пакетах, вам необходимо импортировать пакет, в котором находится соответствующий общедоступный класс. Благодаря наследованию классов все общедоступные методы и переменные класса могут быть унаследованы его подклассами.
Следующие функции используют контроль общего доступа:
public static void main(String[] arguments) { // ... }
Для метода main() программы Java должно быть установлено значение public, иначе интерпретатор Java не сможет запустить класс.
Переменные, методы и конструкторы, объявленные как защищенные, могут быть доступны любому другому классу в том же пакете или подклассам в других пакетах.
Модификаторы защищенного доступа не могут изменять классы и интерфейсы. Методы и переменные-члены могут быть объявлены защищенными, но переменные-члены и методы-члены интерфейсов не могут быть объявлены защищенными.
Подклассы могут получать доступ к методам и переменным, объявленным с модификатором Protected, тем самым защищая несвязанные классы от использования этих методов и переменных.
Следующий родительский класс использует модификатор доступа protected, а подкласс переопределяет метод openSpeaker() родительского класса.
class AudioPlayer { protected boolean openSpeaker(Speaker sp) { // 实现细节} } class StreamingAudioPlayer extends AudioPlayer { boolean openSpeaker(Speaker sp) { // 实现细节} }
Если метод openSpeaker() объявлен закрытым, классы, кроме AudioPlayer, не смогут получить доступ к этому методу.
Если openSpeaker() объявлен как public, все классы могут получить доступ к этому методу.
Если мы хотим, чтобы метод был виден только подклассам его класса, объявите метод как защищенный.
Обратите внимание на следующие правила наследования методов:
Методы, объявленные как общедоступные в родительском классе, также должны быть общедоступными и в дочернем классе.
Методы, объявленные как защищенные в родительском классе, в подклассе объявляются либо как защищенные, либо как общедоступные. Не может быть объявлен частным.
Методы, объявленные как частные в родительском классе, не могут быть унаследованы.
Для реализации некоторых других функций Java также предоставляет множество модификаторов отсутствия доступа.
статический модификатор, используемый для создания методов класса и переменных класса.
Модификатор Final используется для изменения классов, методов и переменных. Классы, измененные с помощью Final, не могут быть унаследованы, измененные методы не могут быть переопределены унаследованными классами, а измененные переменные являются константами и не могут быть изменены.
абстрактный модификатор, используемый для создания абстрактных классов и абстрактных методов.
Модификаторы синхронизированный и изменчивый в основном используются для программирования потоков.
Статические переменные:
Ключевое слово static используется для объявления статических переменных, независимых от объектов. Независимо от того, сколько объектов создает экземпляр класса, существует только одна копия его статических переменных. Статические переменные также известны как переменные класса. Локальные переменные не могут быть объявлены как статические переменные.
Статический метод:
Ключевое слово static используется для объявления статических методов, независимых от объектов. Статические методы не могут использовать нестатические переменные класса. Статические методы получают данные из списка параметров, а затем вычисляют данные.
Доступ к переменным и методам класса можно получить напрямую, используя classname.variablename
и classname.methodname
.
Как показано в следующем примере, модификатор static используется для создания методов класса и переменных класса.
public class InstanceCounter { private static int numInstances = 0; protected static int getCount() { return numInstances; } private static void addInstance() { numInstances++; } InstanceCounter() { InstanceCounter.addInstance(); } public static void main(String[] arguments) { System.out.println("Starting with " + InstanceCounter.getCount() + " instances"); for (int i = 0; i < 500; ++i){ new InstanceCounter(); } System.out.println("Created " + InstanceCounter.getCount() + " instances"); } }
Результаты редактирования приведенного выше примера следующие:
Started with 0 instances Created 500 instances
конечные переменные:
Конечные переменные могут быть инициализированы явно и только один раз. Ссылки на объекты, объявленные как окончательные, не могут указывать на разные объекты. Но данные в конечном объекте можно изменить. Другими словами, ссылку на конечный объект изменить нельзя, но можно изменить значение внутри.
Модификатор Final часто используется вместе с модификатором static для создания констант класса.
Пример:
public class Test{ final int value = 10; // 下面是声明常量的实例public static final int BOXWIDTH = 6; static final String TITLE = "Manager"; public void changeValue(){ value = 12; //将输出一个错误} }
Метод Final в классе может наследоваться подклассами, но не может быть изменен подклассами.
Основная цель объявления финального метода — предотвратить изменение содержимого метода.
Как показано ниже, объявите метод, используя модификатор Final.
public class Test{ public final void changeName(){ // 方法体} }
Финальные классы не могут быть унаследованы, и ни один класс не может наследовать какие-либо характеристики финального класса.
Пример:
public final class Test { // 类体}
Абстрактный класс:
Абстрактные классы не могут использоваться для создания экземпляров объектов. Единственная цель объявления абстрактного класса — расширить его в будущем.
Класс не может быть изменен абстрактным и конечным одновременно. Если класс содержит абстрактные методы, этот класс должен быть объявлен как абстрактный класс, иначе произойдет ошибка компиляции.
Абстрактные классы могут содержать абстрактные и неабстрактные методы.
Пример:
abstract class Caravan{ private double price; private String model; private String year; public abstract void goFast(); //抽象方法public abstract void changeColor(); }
Абстрактный метод — это метод без какой-либо реализации. Конкретная реализация метода предоставляется подклассом. Абстрактные методы не могут быть объявлены окончательными и статическими.
Любой подкласс, наследующий абстрактный класс, должен реализовывать все абстрактные методы родительского класса, если только подкласс также не является абстрактным классом.
Если класс содержит несколько абстрактных методов, класс необходимо объявить абстрактным. Абстрактный класс не обязательно должен содержать абстрактные методы.
Объявление абстрактного метода заканчивается точкой с запятой, например: public Abstract sample();
Пример:
public abstract class SuperClass{ abstract void m(); //抽象方法} class SubClass extends SuperClass{ //实现抽象方法void m(){ ......... } }
К методу, объявленному с ключевым словом Synchronized, одновременно может обращаться только один поток. Модификатор Synchronized можно применить к четырем модификаторам доступа.
Пример:
public synchronized void showDetails(){ ....... }
Когда сериализованный объект содержит переменную экземпляра, которая изменяется с помощью переходного процесса, виртуальная машина Java (JVM) пропускает эту конкретную переменную.
Этот модификатор включен в оператор, определяющий переменную, и используется для предварительной обработки типа данных класса и переменной.
Пример:
public transient int limit = 55; // will not persist public int b; // will persist
Каждый раз, когда поток обращается к изменчивой переменной-члену, значение переменной-члена принудительно пересчитывается из общей памяти. Более того, когда переменная-член изменяется, поток вынужден записать измененное значение обратно в общую память. Таким образом, в любой момент два разных потока всегда видят одно и то же значение переменной-члена.
Ссылка на изменчивый объект может быть нулевой.
Пример:
public class MyRunnable implements Runnable { private volatile boolean active; public void run() { active = true; while (active) // line 1 { // 代码} } public void stop() { active = false; // line 2 } }
Обычно метод run() вызывается в одном потоке, а метод stop() — в другом. Если используется значение active в строке 1 в буфере, то цикл не остановится, если для active в строке 2 установлено значение false.