static ·
‹ Предыдущий Следующий ›
⏱ 5 минут чтения Обновлено: 2026-09-25

Статические переменные в Java

Два разных объекта, две разные записи — staticVars1.b = 3; и staticVars2.b = 4;, — а на экран оба раза выводится 4. Это не ошибка: переменная b объявлена как static, и оба объекта на самом деле работают с одной и той же ячейкой памяти.

Статическая переменная (static-поле, переменная класса) в Java — это поле, объявленное внутри класса с ключевым словом static. Она принадлежит самому классу, а не его объектам: существует в единственном экземпляре на весь класс, создаётся один раз при загрузке и инициализации класса и доступна без создания объекта.

Что означает static в Java

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

При создании объектов копии статических переменных не создаются: сколько бы объектов ни было, статическая переменная одна на весь класс. Её часто сравнивают с глобальной переменной, но это сравнение условное: в Java нет глобальных переменных в привычном смысле — static-поле всегда принадлежит конкретному классу, и его видимость ограничивается модификаторами доступа (private, public и т.д.).

Как и обычные поля, статические переменные получают значения по умолчанию: 0 для числовых типов, false для boolean, null для ссылочных типов.

Статические и обычные переменные: пример

Рассмотрим различие между обычными и статическими переменными на примере. Для обращения к обычной переменной a необходим объект класса StaticVars. К переменной b можно обращаться без упоминания объекта и даже без упоминания класса, если обращение происходит из того же класса:

public class StaticVars {
    int a;
    static int b;

    public static void main(String[] args) {
        StaticVars staticVars = new StaticVars();
        System.out.println(staticVars.a);
        System.out.println(b);
    }
}

Как обращаться к статической переменной

При обращении к статической переменной из другого класса нужно указать имя её класса — StaticVars.b. Технически можно обратиться к ней и через любой объект того же класса, например staticVars1.b или staticVars2.b. Но так делать не рекомендуется: читатель кода может решить, что это обычная переменная объекта, а IDE выдаст предупреждение.

public class StaticVarsExample {
    public static void main(String[] args) {
        StaticVars staticVars1 = new StaticVars();
        StaticVars staticVars2 = new StaticVars();

        System.out.println(StaticVars.b);
        System.out.println(staticVars1.b);

        staticVars1.b = 3;
        staticVars2.b = 4;

        System.out.println(staticVars1.b);
        System.out.println(staticVars2.b);
    }
}

Результат выполнения кода:

0
0
4
4

Обе записи изменили одну и ту же переменную, поэтому последнее присвоенное значение 4 видно через любой объект.

Хорошая практика

Всегда обращайтесь к статической переменной через имя класса: StaticVars.b, а не staticVars1.b. Так сразу видно, что значение общее для всех объектов. Если класс часто использует чужие константы, их можно подключить через static import.

Сравнительная таблица: статическая и обычная переменная

Характеристика Обычная переменная (поле объекта) Статическая переменная (поле класса)
Объявление int a; static int b;
Количество копий Своя у каждого объекта Одна на весь класс
Когда создаётся При создании объекта (new) Один раз при загрузке и инициализации класса
Как обращаться Через объект: obj.a Через имя класса: StaticVars.b
Доступ из static-метода Только через ссылку на объект Напрямую
Типичное применение Состояние конкретного объекта (цвет, имя) Счётчики, константы, общие настройки

Пример: счётчик созданных объектов

Классический пример использования статической переменной — подсчёт количества созданных объектов класса Ball. Для этого объявим в классе статическую переменную count. При создании объекта всегда вызывается конструктор, поэтому именно в нём будем увеличивать count. Для доступа к private переменной count определён статический метод getCount():

public class Ball {
    private static int count = 0;
    String color = "none";

    public Ball(String color) {
        this.color = color;
        count++;
    }

    public static int getCount() {
        return count;
    }
}
public class BallExample {
    public static void main(String[] args) {
        Ball ball1 = new Ball("красный");
        Ball ball2 = new Ball("голубой");
        System.out.println("Количество созданных объектов: "
                + Ball.getCount());
    }
}

Результат выполнения кода:

Количество созданных объектов: 2

У каждого мяча свой color, но count общий: оба конструктора увеличили одну и ту же переменную.

Константы: static final

Самый частый на практике вид статических переменных — константы. Их объявляют с двумя модификаторами сразу: static (одно значение на класс) и final (значение нельзя изменить после присваивания). По соглашению имена констант пишут в верхнем регистре через подчёркивание:

public class AppConfig {
    public static final int MAX_USERS = 100;
    public static final String APP_NAME = "ExamClouds";
    public static final double TAX_RATE = 0.2;
}
public class AppConfigExample {
    public static void main(String[] args) {
        System.out.println(AppConfig.APP_NAME + ": " + AppConfig.MAX_USERS);
        // AppConfig.MAX_USERS = 200; // ошибка компиляции: final-переменную нельзя изменить
    }
}

Если константа примитивного типа или String инициализируется выражением, известным на этапе компиляции, компилятор подставляет её значение прямо в места использования (compile-time constant). Такие константы можно использовать, например, в метках case оператора switch.

Нюанс

final у ссылочной переменной запрещает менять саму ссылку, но не содержимое объекта. Константа static final List<String> NAMES = new ArrayList<>(); по-прежнему позволяет вызвать NAMES.add(...). Для по-настоящему неизменяемой коллекции используйте List.of(...).

Частые ошибки со статическими переменными

  • static у локальной переменной. Внутри метода объявить static int x = 0; нельзя — это ошибка компиляции. Модификатор static допустим только для полей класса.
  • Обращение к обычному полю из static-метода. В main() или любом другом статическом методе нельзя написать просто a, если a — нестатическое поле: компилятор сообщит non-static variable cannot be referenced from a static context. Нужен объект: new StaticVars().a.
  • Изменяемое общее состояние. Статическая переменная видна из всех объектов и потоков. Операция count++ не атомарна, поэтому при создании объектов Ball из нескольких потоков счётчик может «потерять» увеличения. В многопоточном коде используйте AtomicInteger или синхронизацию.
  • Злоупотребление static. Если значение по смыслу относится к конкретному объекту (цвет мяча, имя пользователя), оно не должно быть статическим — иначе все объекты будут перезаписывать одно поле.

Закрепить материал можно на практических задачах по static.

Часто задаваемые вопросы

Где хранятся статические переменные в памяти?

Начиная с JDK 7 (HotSpot) статические поля хранятся в куче (heap) вместе с объектом Class соответствующего класса; до этого они находились в PermGen. В Java 8 PermGen удалена и заменена на Metaspace, где хранятся метаданные классов, но не значения static-полей.

Можно ли обратиться к статической переменной через null-ссылку?

Да, и это популярный вопрос на собеседованиях. Код StaticVars s = null; System.out.println(s.b); не выбросит NullPointerException: компилятор заменяет обращение через переменную на обращение через тип, StaticVars.b, и объект вообще не используется.

Есть ли в Java ключевое слово const?

const в Java зарезервировано, но не используется — объявить с ним переменную нельзя. Константы в Java создаются сочетанием модификаторов static final, например public static final int MAX_USERS = 100;.

Чем static отличается от final?

static определяет, кому принадлежит переменная: классу (одна копия) или объекту (своя копия у каждого). final определяет, можно ли её изменить после присваивания. Модификаторы независимы: бывают static-переменные без final (счётчик), final-поля без static (неизменяемый id объекта) и их сочетание — константы.

Когда инициализируется статическая переменная?

Один раз при инициализации класса — перед первым созданием объекта, первым вызовом статического метода или первым обращением к статическому полю (кроме compile-time констант). Инициализаторы static-полей и статические блоки выполняются в порядке их объявления в классе.

Видео объяснение

Предпочитаете видеоформат? Посмотрите этот урок с примерами и объяснениями.

Комментарии

Зарегистрируйтесь или войдите, чтобы иметь возможность оставить комментарий.