Menu

Статические члены в Java: static-поля и методы

Что делает ключевое слово static в Java, как static-поля и методы принадлежат классу, а не объектам, и когда стоит прибегать к static-блокам и константам.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Принадлежность классу, а не объекту

Большинство полей и методов, которые вы писали до сих пор, принадлежат объектам: каждый раз, когда вы вызываете new, каждый экземпляр получает собственную копию полей, а методы работают с состоянием конкретного объекта. Ключевое слово static переворачивает это. static-член принадлежит самому классу — существует одна-единственная копия, общая для всех экземпляров, и она существует независимо от того, создадите ли вы хоть один объект.

Это единственное различие объясняет static-поля, static-методы, константы и даже то, почему main всегда static.

Общее static-поле

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

Обратите внимание, что вы читаете счётчик как User.count — через имя класса, потому что значение не принадлежит ни одному конкретному User. Каждое name, напротив, живёт внутри своего объекта. Измените count через любой экземпляр — и все экземпляры увидят новое значение, потому что оно одно.

static-методы

static-метод тоже принадлежит классу, поэтому вы вызываете его на классе без объекта:

Именно этот приём лежит в основе стандартной библиотеки: Math.max, Integer.parseInt, Arrays.sort и List.of — все они static, это служебное поведение, которому не нужен объект для работы. Прибегайте к static-методу, когда работа зависит только от аргументов, а не от состояния какого-либо объекта.

Главная ловушка: static не видит instance

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

class Account {
    int balance = 100;          // поле экземпляра

    static int show() {
        return balance;         // ОШИБКА КОМПИЛЯЦИИ: к нестатическому полю 'balance'
    }                           // нельзя обратиться из статического контекста
}

Исправление: либо сделать метод методом экземпляра (убрать static, чтобы у него появился this), либо передать объект явно:

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

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

Сочетайте static с final — и получите константу: одно общее значение, которое никогда не может измениться. По соглашению их называют в стиле UPPER_SNAKE_CASE:

static final — идиоматичный способ выразить «фиксированное значение, принадлежащее типу», как, например, Integer.MAX_VALUE или Math.PI в стандартной библиотеке. Сделать его static — значит не тратить по копии на каждый объект; сделать его final — значит никто не сможет его переприсвоить.

Статические блоки инициализации

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

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

Когда использовать static

Быстрое правило:

  • Используйте static-поле только для данных, которые действительно общие для всех экземпляров — счётчик, кеш, константа. Если два объекта могут разумно хранить разные значения, это должно быть поле экземпляра.
  • Используйте static-метод, когда результат зависит только от аргументов, а не от состояния какого-либо объекта (чистые служебные функции).
  • По умолчанию выбирайте члены экземпляра. Злоупотребление static незаметно превращает программу в кучу глобального состояния, которое трудно тестировать и понимать. static — это исключение, а не отправная точка.

Далее: перечисления (Enum)

Константа static final хороша для одного фиксированного значения, но когда у вас есть небольшой фиксированный набор связанных значений — направления, дни недели, статусы заказа — в Java есть специально созданный тип, более безопасный и выразительный, чем разрозненные константы. Это enum, и о нём — следующая страница.

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

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

static означает, что поле или метод принадлежит самому классу, а не отдельному объекту. Существует ровно одна копия static-поля, общая для всех экземпляров, и static-метод вызывается на классе (Math.max(...)) без необходимости в объекте. Нестатические члены (экземпляра), напротив, получают новую копию для каждого объекта.

В чём разница между static-переменными и переменными экземпляра в Java?

У переменной экземпляра есть одно значение на объект — два объекта могут хранить разные значения. У static-переменной единственное значение, общее для всех объектов класса, поэтому её изменение через один объект (или через имя класса) видно всем остальным. Используйте поля экземпляра для состояния, своего у каждого объекта, и static-поля для данных, по-настоящему общих для всего класса, например счётчика или константы.

Почему метод main в Java объявлен static?

JVM должна вызвать main до того, как появится хоть один объект вашего класса. Поскольку static-метод принадлежит классу, а не экземпляру, среда выполнения может напрямую вызвать Main.main(args), не создавая сначала Main. Именно поэтому сигнатура всегда выглядит как public static void main(String[] args).

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ