1. Обзор
В этом руководстве мы подробно рассмотрим ключевое слово static языка Java.
Мы узнаем, как мы можем применять ключевое слово static
к переменным, методам, блокам и вложенным классам, и какое это имеет значение.
2. Анатомия статического
ключевого слова
В языке программирования Java ключевое слово static
означает, что конкретный член принадлежит самому типу, а не экземпляру этого типа.
Это означает, что мы создадим только один экземпляр этого статического члена, который будет общим для всех экземпляров класса.
Мы можем применить ключевое слово к переменным, методам, блокам и вложенным классам.
3. Статические
поля (или переменные класса)
В Java, когда мы объявляем поле static
, создается ровно одна копия этого поля, которая используется всеми экземплярами этого класса.
Неважно, сколько раз мы инициализируем класс. Всегда будет только одна копия принадлежащего ему статического
поля. Значение этого статического
поля будет общим для всех объектов одного или любого другого класса.
С точки зрения памяти статические переменные хранятся в куче памяти.
3.1. Пример статического
поля
Допустим, у нас есть класс Car
с несколькими атрибутами (переменными экземпляра) .
Всякий раз, когда мы инициализируем новые объекты из этого Car
blueprint, каждый новый объект будет иметь свою отдельную копию этих переменных экземпляра.
Однако предположим, что нам нужна переменная, которая содержит количество инициализированных объектов Car
и является общей для всех экземпляров, чтобы они могли получить к ней доступ и увеличить ее при инициализации.
Вот где появляются статические
переменные:
public class Car {
private String name;
private String engine;
public static int numberOfCars;
public Car(String name, String engine) {
this.name = name;
this.engine = engine;
numberOfCars++;
}
// getters and setters
}
Теперь для каждого объекта этого класса, который мы инициализируем, увеличивается одна и та же копия переменной numberOfCars .
Итак, для этого случая будут верны:
@Test
public void whenNumberOfCarObjectsInitialized_thenStaticCounterIncreases() {
new Car("Jaguar", "V8");
new Car("Bugatti", "W16");
assertEquals(2, Car.numberOfCars);
}
3.2. Веские причины использовать статические
поля
- Когда значение переменной не зависит от объектов
- Когда значение должно быть общим для всех объектов
3.3. Ключевые моменты, которые следует помнить
- Поскольку
статические
переменные принадлежат классу, мы можем получить к ним прямой доступ, используя имя класса. Итак, нам не нужна ссылка на объект. - Мы можем объявлять
статические
переменные только на уровне класса. - Мы можем получить доступ к
статическим
полям без инициализации объекта. - Наконец, мы можем получить доступ к
статическим
полям, используя ссылку на объект (например,ford.numberOfCars++
). Но мы должны избегать этого, потому что становится трудно понять, является ли это переменной экземпляра или переменной класса. Вместо этого мы всегда должны ссылаться настатические
переменные, используя имя класса (Car.numberOfCars++
).
4. Статические
методы (или методы класса)
Подобно статическим
полям, статические
методы также принадлежат классу, а не объекту. Таким образом, мы можем вызывать их, не создавая объект класса, в котором они находятся.
4.1. Пример статического
метода
Обычно мы используем статические
методы для выполнения операции, которая не зависит от создания экземпляра.
Чтобы разделить код между всеми экземплярами этого класса, мы пишем этот код в статическом
методе:
public static void setNumberOfCars(int numberOfCars) {
Car.numberOfCars = numberOfCars;
}
Мы также обычно используем статические
методы для создания служебных или вспомогательных классов, чтобы мы могли получить их, не создавая новый объект этих классов.
Просто взгляните на служебные классы Collections или Math из JDK, StringUtils из Apache или CollectionUtils из Spring framework и обратите внимание, что все методы являются статическими
.
4.2. Веские причины использовать статические
методы
- Для доступа/манипулирования статическими переменными и другими статическими методами, которые не зависят от объектов
статические
методы широко используются в служебных и вспомогательных классах.
4.3. Ключевые моменты, которые следует помнить
статические
методы в Java разрешаются во время компиляции. Поскольку переопределение методов является частью полиморфизма времени выполнения, статические методы нельзя переопределять.- Абстрактные методы не могут быть статическими.
статические
методы не могут использовать ключевые словаthis
илиsuper
.- Допустимы следующие комбинации экземпляра, методов класса и переменных:
- Методы экземпляра могут напрямую обращаться как к методам экземпляра, так и к переменным экземпляра.
- Методы экземпляра также могут напрямую обращаться к
статическим
переменным истатическим методам.
статические
методы могут обращаться ко всемстатическим
переменным и другимстатическим
методам.статические
методы не могут напрямую обращаться к переменным экземпляра и методам экземпляра. Для этого им нужна некоторая ссылка на объект.
5. Статический
блок
Мы используем статический
блок для инициализации статических
переменных. Хотя мы можем инициализировать статические
переменные непосредственно во время объявления, бывают ситуации, когда нам нужно выполнить многострочную обработку.
В таких случаях на помощь приходят статические
блоки.
Если статические
переменные требуют дополнительной логики с несколькими операторами во время инициализации, мы можем использовать статический
блок.
5.1. Пример статического
блока
Предположим, мы хотим инициализировать объект списка некоторыми предопределенными значениями.
Это становится легко со статическими
блоками:
public class StaticBlockDemo {
public static List<String> ranks = new LinkedList<>();
static {
ranks.add("Lieutenant");
ranks.add("Captain");
ranks.add("Major");
}
static {
ranks.add("Colonel");
ranks.add("General");
}
}
Было бы невозможно инициализировать объект List
со всеми начальными значениями вместе с объявлением. Вот почему мы использовали здесь статический
блок.
5.2. Веские причины использовать статические
блоки
- Если для инициализации
статических
переменных нужна дополнительная логика, кроме присваивания - Если инициализация
статических
переменных подвержена ошибкам и требует обработки исключений
5.3. Ключевые моменты, которые следует помнить
- Класс может иметь несколько
статических
блоков. статические
поля истатические
блоки разрешаются и выполняются в том же порядке, в котором они присутствуют в классе.
6. Статический
класс
Язык программирования Java позволяет нам создавать класс внутри класса. Он обеспечивает убедительный способ группировки элементов, которые мы будем использовать только в одном месте. Это помогает сделать наш код более организованным и читабельным.
Архитектура вложенных классов делится на две части:
- Вложенные классы, которые мы объявляем
статическими
, называютсястатическими
вложенными классами. - Вложенные классы, которые не являются
статическими
, называются внутренними классами.
Основное различие между ними состоит в том, что внутренние классы имеют доступ ко всем членам окружающего класса (включая закрытые), тогда как статические
вложенные классы имеют доступ только к статическим членам внешнего класса.
На самом деле, статические
вложенные классы ведут себя точно так же, как и любой другой класс верхнего уровня, но заключены в единственный класс, который будет иметь к нему доступ, чтобы обеспечить лучшее удобство упаковки.
6.1. Пример статического
класса
Наиболее широко используемый подход к созданию одноэлементных объектов — через статический
вложенный класс:
public class Singleton { private Singleton() {}
частный статический класс SingletonHolder {
открытый статический конечный экземпляр Singleton = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
Мы используем этот метод, потому что он не требует синхронизации и прост в освоении и реализации.
6.2. Веские причины использовать статический
внутренний класс
- Группировка классов, которые будут использоваться только в одном месте, увеличивает инкапсуляцию.
- Мы приближаем код к единственному месту, где он будет использоваться. Это повышает удобочитаемость и упрощает сопровождение кода.
- Если вложенный класс не требует какого-либо доступа к окружающим его членам экземпляра класса, лучше объявить его как
static
. Таким образом, он не будет связан с внешним классом и, следовательно, более оптимален, поскольку ему не потребуется память кучи или стека.
6.3. Ключевые моменты, которые следует помнить
статические
вложенные классы не имеют доступа ни к каким членам экземпляра внешнего класса. Он может получить к ним доступ только через ссылку на объект.статические
вложенные классы могут получить доступ ко всем статическим членам окружающего класса, включая закрытые.- Спецификация программирования Java не позволяет нам объявлять класс верхнего уровня как
статический
.Статичными
могут быть только классы внутри классов (вложенные классы) .
7. Заключение
В этой статье мы увидели ключевое слово static
в действии.
Мы также читаем о причинах и преимуществах использования статических полей, статических методов, статических блоков и статических внутренних классов.
Как всегда, мы можем найти полный код на GitHub .