Для чего статические переменные
Статические переменные
1. Статические переменные
Когда класс загружается в память, для него сразу создается статический объект класса. Этот объект хранит статические переменные класса (статические поля класса). Статический объект класса существует, даже если не был создан ни один обычный объект класса.
Когда мы описываем переменные в классе, мы указываем, будут ли эти переменные созданы всего один раз или же нужно создавать их копии для каждого объекта. По умолчанию создаётся новая копия переменной для каждого объекта.
Статическая (static) же переменная привязана к статическому объекту класса и всегда существует в единственном экземпляре.
Если статической переменной не присвоить стартовое значение, она инициализируется значением по умолчанию:
Тип | Значение по умолчанию |
---|---|
(то же самое, что и ) | |
и любые классы |
Обращаться к статической переменной в ее классе можно просто по имени. Если обращение идет из другого класса, то перед именем статической переменной нужно писать имя класса.
2. Отличие статических и нестатических переменных
Чем же отличаются обычные и статические переменные?
Обычные переменные класса привязаны к объектам своего класса (экземплярам класса), статические переменные — к статическому объекту класса.
Если экземпляров класса несколько, в каждом из них существует своя копия нестатических (обычных) переменных класса. Статические переменные класса всегда находятся внутри статического объекта класса и существуют только в одном экземпляре.
Обращаться к обычным переменным класса (полям класса) можно только имея ссылку на объект класса. Ну или в методах внутри этого же класса.
Обращение к полю класса с использованием ссылки на объект класса |
---|
Обращаться к статическим переменным можно откуда угодно (с учетом модификаторов видимости): из обычных методов, из статических методов того же класса, из методов других классов и т.п.
Обращение к статическому полю класса не используя ссылку на объект класса |
---|
Устройство в памяти:
Допустим, у нас есть класс Person с 4 полями: два статических, а два — нет.
Сразу после загрузки класса
После создания первого объекта
Обратите внимание, что хоть у объектов по две переменные, это разные переменные: у обычного объекта — обычные, у статического — статические.
Нужно больше объектов
Обратите внимание: у каждого объекта есть собственная переменная age и name.
Урок №124. Статические переменные-члены класса
Обновл. 24 Сен 2021 |
На этом уроке мы рассмотрим использование статических переменных-членов класса в языке С++.
Статические переменные-члены класса
Из урока №51 мы узнали, что статические переменные сохраняют свои значения и не уничтожаются даже после выхода из блока, в котором они объявлены, например:
Результат выполнения программы:
Обратите внимание, s_id сохраняет свое значение после каждого вызова функции generateID().
Ключевое слово static имеет другое значение, когда речь идет о глобальных переменных — оно предоставляет им внутреннюю связь (что ограничивает их видимость/использование за пределами файла, в котором они определены). Поскольку использование глобальных переменных — это зло, то ключевое слово static в этом контексте используется не очень часто.
В языке C++ ключевое слово static можно использовать в классах: статические переменные-члены и статические методы. Мы поговорим о статических переменных-членах на этом уроке, а о статических методах на следующем.
Прежде чем мы перейдем к ключевому слову static с переменными-членами класса, давайте сначала рассмотрим следующий класс:
Переменные-члены класса можно сделать статическими, используя ключевое слово static. В отличие от обычных переменных-членов, статические переменные-члены являются общими для всех объектов класса. Рассмотрим следующую программу:
Результат выполнения программы:
Статические члены не связаны с объектами класса
Хотя вы можете получить доступ к статическим членам через разные объекты класса (как в примере, приведенном выше), но, оказывается, статические члены существуют, даже если объекты класса не созданы! Подобно глобальным переменным, они создаются при запуске программы и уничтожаются, когда программа завершает свое выполнение.
Следовательно, статические члены принадлежат классу, а не объектам этого класса. Поскольку s_value существует независимо от любых объектов класса, то доступ к нему осуществляется напрямую через имя класса и оператор разрешения области видимости (в данном случае, через Anything::s_value ):
В вышеприведенном фрагменте доступ к s_value осуществляется через имя класса, а не через объект этого класса. Обратите внимание, мы даже не создавали объект класса Anything, но мы все равно имеем доступ к Anything::s_value и можем использовать эту переменную-член.
Определение и инициализация статических переменных-членов класса
Когда мы объявляем статическую переменную-член внутри тела класса, то мы сообщаем компилятору о существовании статической переменной-члене, но не о её определении (аналогией является предварительное объявление). Поскольку статические переменные-члены не являются частью отдельных объектов класса (они обрабатываются аналогично глобальным переменным и инициализируются при запуске программы), то вы должны явно определить статический член вне тела класса — в глобальной области видимости.
В программе, приведенной выше, это делается следующей строкой кода:
Инициализация статических переменных-членов внутри тела класса
Есть несколько обходных путей определения статических членов внутри тела класса. Во-первых, если статический член является константным интегральным типом (к которому относятся и char, и bool) или константным перечислением, то статический член может быть инициализирован внутри тела класса:
Поскольку здесь статическая переменная-член является целочисленной константой, то дополнительной строки явного определения вне тела класса уже не требуется.
Во-вторых, начиная с C++11 статические члены constexpr любого типа данных, поддерживающие инициализацию constexpr, могут быть инициализированы внутри тела класса:
Статические переменные и методы
— Новая интересная тема. Хочу рассказать тебе о статических переменных и методах.
— О, я уже слышал про статические переменные. И про статические методы, кажется. Но хотелось бы больше подробностей.
— Когда мы описываем переменные в классе, мы указываем, будут ли эти переменные созданы всего один раз или же нужно создавать их копии для каждого объекта. По умолчанию создаётся новая копия переменной для каждого объекта. Вот как это выглядит:
— Методы класса тоже делятся на две категории. Обычные методы вызываются у объекта и имеют доступ к данным этого объекта. Статические методы не имеют такого доступа – у них просто нет ссылки на объект, они способны обращаться либо к статическим переменным этого класса либо к другим статическим методам.
— Статические методы не могут обращаться к нестатическим методам или нестатическим переменным!
— Каждая обычная переменная класса находится внутри объекта. Обратиться к ней можно только имея ссылку на этот объект. В статический метод такая ссылка не передается.
— А в обычные методы передается?
— В статический метод вместо ссылки на объект передается null. Поэтому он не может обращаться к нестатическим переменным и методам – у него банально нет ссылки на объект, к которому они привязаны.
— Так работают обычные нестатические методы:
— А вот как работают статические методы:
— Переменная или метод являются статическими, если перед ними стоит ключевое слово static.
— А зачем такие методы нужны, если они так сильно ограничены?
— У такого подхода тоже есть свои преимущества.
— Во-первых, для того, чтобы обратиться к статическим методам и переменным не надо передавать никакую ссылку на объект.
— Во-вторых, иногда бывает нужно, чтобы переменная была в единственном экземпляре. Как, например, переменная System.out (статическая переменная out класса System).
— И в третьих, иногда нужно вызвать метод, еще до того, как будет возможность создавать какие-то объекты
— А почему, по-твоему, метод main объявлен статическим? Чтобы его можно было вызвать сразу после загрузки класса в память. Еще до того, когда можно будет создавать какие-то объекты.
BestProg
Статические классы, методы, переменные. Статические конструкторы. Ключевое слово static
Содержание
Поиск на других ресурсах:
1. Какие элементы языка программирования C# можно объявлять статическими?
В языке программирования C# статическими могут быть:
⇑
2. Понятие статического класса. Какие особенности использования статических классов в программах на C#? Ключевое слово static
С точки зрения синтаксиса C# статический класс – это класс, который объявляется с ключевым словом static.
Общая форма объявления статического класса:
где ClassName – имя статического класса.
⇑
3. Свойства статического класса
Реализация программного кода статического класса ничем не отличается от программного кода обычного класса за исключением двух основных свойств. В сравнении с нестатическим классом, статический класс имеет следующие свойства (отличия):
⇑
4. Примеры, которые демонстрируют свойства статического класса
Если попробовать создать объект статического класса
то возникнет ошибка компиляции с сообщением:
то во время компиляции компилятор выдаст следующую ошибку:
⇑
5. Примеры статических классов
Программный код классов Count и Methods следующий:
Если в данном примере класс Count объявить как нестатический (без ключевого слова static )
то результат работы программы не изменится. Статическую переменную Count.count можно использовать как общий ресурс.
Пример 2. Пример демонстрирует использование статического метода в нестатическом классе. Статический метод выступает общим ресурсом, который выполняет некоторую общую работу.
⇑
6. Какие преимущества применения статических классов, методов и переменных в программах на C#?
Статические классы, методы и переменные эффективны в следующих случаях:
⇑
7. Чем отличается вызов статического метода от нестатического?
В любом нестатическом классе могут быть объявлены как статические методы, так и нестатические. Отличие между вызовом статического и нестатического метода класса состоит в следующем:
Ниже демонстрируется вызов и использование этих методов:
Как видно из вышеприведенного кода, чтобы вызвать статический метод некоторого класса, перед его именем нужно указать имя этого класса.
⇑
8. Можно ли объявить скрытый ( private ) статический член в некотором классе?
Да можно. В этом случае этот статический член класса будет доступным только в границах этого класса, то есть из методов этого класса. Доступ из методов других классов будет невозможен.
⇑
Да можно. В этом случае, доступ к статического члену класса будут иметь методы класса, которые унаследованы от данного класса.
⇑
10. Может ли нестатический класс содержать статические переменные и статические методы?
Да может. Примеры использования статических методов в нестатическом классе приведены в пунктах 5 и 7.
⇑
11. Можно ли объединять статические и нестатические методы в одном классе?
Да, можно. Но только в нестатическом классе. Если класс объявлен как статический, то все методы и переменные класса должны быть также статическими (см. п. 4 — Пример 2).
В нижеследующем коде продемонстрирован доступ к скрытой статической переменной t класса CMyClass
Данный пример хорошо демонстрирует, как можно организовать работу с общими, скрытыми данными класса.
⇑
12. Можно ли в статическом методе статического класса создать объект нестатического класса?
⇑
13. Что такое статические конструкторы? Пример
Статические конструкторы позволяют инициализировать статические переменные класса.
Пример. Демонстрируется объявление статического конструктора в классе.
Демонстрация работы класса CCount в некотором методе
⇑
14. Какие правила (особенности) использования статических конструкторов?
При использовании статических конструкторов нужно обратить внимание на следующие правила:
⇑
15. Можно ли из статических конструкторов инициализировать нестатические переменные класса?
Нет, нельзя. Из статических конструкторов можно инициализировать только статические переменные этого же класса. Если в этом классе также объявляются нестатические переменные, то доступа к ним из статических конструкторов нету.
Все о ключевых словах static и final
Что такое ключевое слово static?
Чтобы получить доступ к членам класса в Java, нужно сначала создать экземпляр класса, а затем вызвать членов класса с помощью переменной экземпляра. Но иногда нужно получить доступ к членам класса, не создавая никаких переменных.
Где можно употреблять ключевое слово static?
Мы можем использовать это ключевое слово в четырех контекстах:
Рассмотрим подробнее каждый из перечисленных пунктов.
Статические методы
Статические методы также называются методами класса, потому что статический метод принадлежит классу, а не его объекту. Кроме того, статические методы можно вызывать напрямую через имя класса.
Статические переменные
При создании объектов класса в Java каждый из них содержит собственную копию всех переменных класса.
Однако, если мы объявим переменную статической, все объекты класса будут использовать одну и ту же статическую переменную. Это связано с тем, что, как и статические методы, статические переменные также связаны с классом. И объекты класса для доступа к статическим переменным создавать не нужно. Например:
В приведенном выше примере normalVariable — переменная класса, а staticVariable — статическая переменная. Если вы объявите переменную, как показано ниже:
Это похоже на доступ к статической переменной через имя класса:
Здесь статические переменные — переменные уровня класса. Поэтому, если вы обращаетесь к статическим переменным через переменную экземпляра объекта, то это отражается на соответствующей статической переменной уровня класса. Таким образом, статические переменные всегда имеют одно и то же значение. Но переменная экземпляра сохраняет отдельное значение в каждом экземпляре объекта. Таким образом, приведенный выше фрагмент кода выведет:
Статические переменные — редкость в Java. Вместо них применяют статические константы. Они определяются ключевым словом static final и представлены в верхнем регистре. Вот почему некоторые предпочитают использовать верхний регистр и для статических переменных.
Статические блоки
Здесь мы видим статический блок с синтаксисом:
Статические блоки применяют для инициализации статических переменных. Статический блок выполняется только один раз, когда класс загружается в память. Это происходит, если в коде запрашивается либо объект класса, либо статические члены этого класса.
Класс может содержать несколько статических блоков, а каждый из них выполняется в той же последовательности, в которой они написаны в коде.
Вывод приведенного выше фрагмента кода выглядит следующим образом, потому что переменная staticVariable обновлена вторым значением статического блока.
Вложенный статический класс
В Java можно объявить класс внутри другого класса. Такие классы называются вложенными классами. Они бывают двух типов: статические и нестатические.
Вложенный класс является членом заключающего его класса. Нестатические вложенные классы (внутренние классы) имеют доступ к другим членам заключающего класса, даже если они объявлены приватными. Статические вложенные классы не имеют доступа к другим членам заключающего класса.
Внутренний класс по умолчанию содержит неявную ссылку на объект внешнего класса. Если вы создадите экземпляр этого объекта из кода внешнего класса, все будет сделано за вас. Если вы поступите иначе, вам необходимо предоставить объект самостоятельно.
Со статическим внутренним классом все иначе. Можно сказать, что если у внутреннего класса нет причин для доступа к внешнему, вы должны сделать его статическим по умолчанию.
В приведенном выше примере видно, что внутренний класс MyInnerClass может получить доступ ко всем методам и переменным внешнего, включая приватные переменные. Статическому внутреннему классу, напротив, недоступны какие-либо методы или переменные внешнего класса.
Где в памяти Java хранятся статические классы и переменные?
Вплоть до 8-й версии Java статические методы и переменные хранились в пространстве permgen. Но потом было введено новое пространство памяти, называемое метапространством — в нем хранятся все эти имена и поля класса, методы класса с байт-кодом методов, пул констант, JIT-оптимизации и т. д. Причина удаления permgen в Java 8.0 в том, что очень сложно предсказать необходимый размер permgen.
Зачем нужно ключевое слово final?
Что такое конечная переменная и когда ей стоит воспользоваться?
Существует три способа инициализации конечной переменной.
Когда следует применять конечную переменную
Единственное различие между обычной и конечной переменной в том, что первой можно переприсвоить значение, а второй — нельзя. Следовательно, конечные переменные должны использоваться только для значений, которые необходимо сохранять постоянными на протяжении выполнения программы.
Где использовать конечные классы
При попытке расширить конечный класс компилятор выдаст следующее исключение:
Когда использовать конечные методы
Здесь происходит попытка переопределить метод final из родительского класса. Java этого не позволяет и выдает следующее исключение: