Руководство по статическому ключевому слову в Java

Руководство по статическому ключевому слову в Java

1. Вступление

В этой статье мы подробно рассмотрим ключевое словоstatic в языке Java. Мы узнаем, как применить ключевое словоstatic к переменным, методам, блокам, вложенным классам и какую разницу оно имеет.

2. Анатомия ключевого словаstatic

В языке программирования Javathe keyword static indicates that the particular member belongs to a type itself, rather than to an instance of that type.

Это означает, что создается только один экземпляр этого статического члена, который является общим для всех экземпляров класса.

image

Ключевое слово может быть применено к переменным, методам, блокам и вложенному классу.

3. Поляstatic (или переменные класса)

В Javaif a field is declared static, then exactly a single copy of that field is created and shared among all instances of that class. Не имеет значения, сколько раз мы инициализируем класс; всегда будет принадлежать только одна копия поляstatic. Значение этого поляstatic будет совместно использоваться всеми объектами одного и того же любого другого класса.

С точки зрения памяти,static variables go in a particular pool in JVM memory called Metaspace (до Java 8 этот пул назывался Permanent Generation или PermGen, который был полностью удален и заменен на Metaspace).

3.1. Пример поляstatic

Предположим, у нас есть классCar с несколькими атрибутами (переменными экземпляра).. Каждый раз, когда новые объекты инициализируются из этого чертежаCar, каждый новый объект будет иметь свою отдельную копию этих переменных экземпляра.

Однако предположим, что мы ищем переменную, которая содержит счетчик числа инициализированных объектовCar и является общедоступной для всех экземпляров, чтобы они могли получить к ней доступ и увеличивать ее при инициализации.

Вот тут и пригодятся переменныеstatic:

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. Неопровержимые причины использовать поляstatic

  • Когда значение переменной не зависит от объектов

  • Когда значение должно быть общим для всех объектов

3.3. Ключевые моменты, которые следует помнить

  • Поскольку переменныеstatic принадлежат классу, к ним можно получить доступ напрямую, используя имя класса, и им не нужна ссылка на объект.

  • Переменныеstatic могут быть объявлены только на уровне класса

  • Доступ к полямstatic возможен без инициализации объекта

  • Хотя мы можем получить доступ к полямstatic, используя ссылку на объект (например,ford.numberOfCars_) , we should refrain from using it as in this case it becomes difficult to figure whether it’s an instance variable or a class variable; instead, we should always refer to _static_ variables using class name (for example, in this case, _Car.numberOfCars)

4. Методыstatic (или методы класса)

Подобно полямstatic, методыstatic также принадлежат классу, а не объекту, поэтому их можно вызывать без создания объекта класса, в котором они находятся. Они предназначены для использования без создания объектов класса.

4.1. Пример методаstatic

Методыstatic обычно используются для выполнения операции, не зависящей от создания экземпляра.

Если есть код, который предполагается использовать для всех экземпляров этого класса, напишите этот код в методеstatic:

public static void setNumberOfCars(int numberOfCars) {
    Car.numberOfCars = numberOfCars;
}

Методыstatic также широко используются для создания служебных или вспомогательных классов, так что их можно получить без создания нового объекта этих классов.

Просто взгляните на служебные классыCollections илиMath из JDK,StringUtils из Apache илиCollectionUtils из Spring framework и обратите внимание, что все методы -static.

4.2. Неопровержимые причины использовать методыstatic

  • Для доступа / управления статическими переменными и другими статическими методами, которые не зависят от объектов

  • Методыstatic широко используются в служебных и вспомогательных классах.

4.3. Ключевые моменты, которые следует помнить

  • Методыstatic в Java разрешаются во время компиляции. Поскольку переопределение метода является частью полиморфизма времени выполнения,so static methods can’t be overridden

  • абстрактные методы не могут быть статическими

  • Методыstatic не могут использовать ключевые словаthis илиsuper

  • Допустимы следующие комбинации экземпляра, методов класса и переменных:

    1. Методы экземпляра могут напрямую обращаться как к методам экземпляра, так и к переменным экземпляра.

    2. Методы экземпляра также могут напрямую обращаться к переменнымstatic и методамstatic

    3. Методыstatic могут обращаться ко всем переменнымstatic и другим методамstatic

    4. static methods cannot access instance variables and instance methods directly; для этого им нужна ссылка на объект

5. Блок Astatic

Блокstatic используется для инициализации переменныхstatic. Хотя переменныеstatic могут быть инициализированы непосредственно во время объявления, бывают ситуации, когда нам требуется выполнять многострочную обработку.

В таких случаях могут пригодиться блокиstatic.

Если переменныеstatic требуют дополнительной логики с несколькими операторами при инициализации, то можно использовать блокstatic.

5.1. Пример блокаstatic

Предположим, мы хотим инициализировать объект списка с некоторыми предопределенными значениями.

Это становится легко с блокамиstatic:

public class StaticBlockDemo {
    public static List ranks = new LinkedList<>();

    static {
        ranks.add("Lieutenant");
        ranks.add("Captain");
        ranks.add("Major");
    }

    static {
        ranks.add("Colonel");
        ranks.add("General");
    }
}

В этом примере было бы невозможно инициализировать объектList всеми начальными значениями вместе с объявлением; и поэтому мы использовали здесь блокstatic.

5.2. Неопровержимые причины использовать блокиstatic

  • Если для инициализации переменныхstatic требуется дополнительная логика, кроме присваивания

  • Если инициализация статических переменных подвержена ошибкам и требует обработки исключений

5.3. Ключевые моменты, которые следует помнить

  • Класс может иметь несколько блоковstatic

  • Поляstatic и блокиstatic разрешаются и выполняются в том же порядке, в котором они присутствуют в классе

6. Класс Astatic

Язык программирования Java позволяет нам создавать класс внутри класса. Это обеспечивает убедительный способ группировки элементов, которые будут использоваться только в одном месте, это помогает сделать наш код более организованным и читаемым.

Архитектура вложенного класса делится на две части:

  • вложенные классы, объявленныеstatic, называютсяstatic nested classes, тогда как

  • вложенные классы, которые не являются -static, называютсяinner classes

Основное различие между этими двумя состоит в том, что внутренние классы имеют доступ ко всем членам включающего класса (включая частные), тогда как вложенные классыstatic имеют доступ только к статическим членам внешнего класса.

Фактическиstatic nested classes behaved exactly like any other top-level class but enclosed in the only class which will access it, to provide better packaging convenience.

6.1. Пример классаstatic

Наиболее широко используемый подход для создания одноэлементных объектов - это вложенный классstatic, поскольку он не требует никакой синхронизации, его легко изучить и реализовать:

public class Singleton  {
    private Singleton() {}

    private static class SingletonHolder {
        public static final Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}

6.2. Неопровержимые причины для использования внутреннего классаstatic

  • Группировка классов, которые будут использоваться только в одном месте, увеличивает инкапсуляцию

  • Код приближен к тому месту, где его будет использовать только один; это увеличивает читабельность и код более удобен в обслуживании

  • Если вложенный класс не требует доступа к членам экземпляра класса, который включает в себя, то лучше объявить его какstatic, потому что в этом случае он не будет связан с внешним классом и, следовательно, будет более оптимальным, поскольку они не требует памяти кучи или стека

6.3. Ключевые моменты, которые следует помнить

  • static nested classes do not have access to any instance members of the enclosing outer class; он может получить к ним доступ только через ссылку на объект

  • Статические вложенные классы могут обращаться ко всем статическим членам включающего класса, включая закрытые.

  • Спецификация программирования Java не позволяет нам объявить класс верхнего уровня какstatic; только классы внутри классов (вложенные классы) могут быть сделаны какstatic

7. Заключение

В этой статье мы увидели ключевое словоstatic в действии. Мы также читаем о причинах и преимуществах использования статических полей, статических методов, статических блоков и статических внутренних классов.

Как всегда, мы можем найти полный кодover on GitHub.