Разница между статическими переменными-членами и нестатическими переменными-членами
В качестве примера возьмите следующий пример
package cn.galc.test;public class Cat { /** * Статическая переменная-член */ Private static int sid = 0; Private String name; Cat(String name) { this.name = name; } public void info() { System.out.println("Меня зовут " + name + ",NO." + id } public static void main(String[] args) { Cat.sid); = 100; Кот мими = новый кот("мими"); Кот пипи = новый кот("пипи.info()); pipi.info();Понимать процесс выполнения всей программы, рисуя диаграммы анализа памяти.
При выполнении первого предложения программы: Cat.sid = 100;, sid здесь является статической переменной-членом. Статическая переменная хранится в области данных (сегмент данных), поэтому сначала выделите небольшое пространство sid в области данных. После выполнения предложения sid содержит значение 100.
Схема расположения памяти на данный момент выглядит следующим образом:
Далее программа выполняет:
Кот Мими = новый Кот («Мими»);
Здесь вызывается метод конструктора Cat(String name) класса Cat. Метод конструктора определяется следующим образом:
Cat (имя строки) { this.name = name; id=sid++ }; При вызове сначала выделите небольшой участок памяти mm в памяти стека, который содержит адрес объекта экземпляра класса Cat в памяти кучи. mm — это ссылочный объект объекта класса Cat в памяти кучи. Этот конструктор объявляет формальную переменную-параметр строкового типа, поэтому "mimi" передается конструктору как фактический параметр. Поскольку строковая константа выделяется и сохраняется в области данных, в области данных имеется дополнительный небольшой фрагмент памяти. . Используется для хранения строки «мими». Распределение памяти в это время показано на рисунке ниже:
При вызове конструктора сначала выделите небольшое пространство в памяти стека для имени формального параметра, а затем передайте строку «mimi» в качестве фактического параметра для имени. Эта строка также является ссылочным типом, за исключением этих четырех и восьми. базовые типы данных, все остальные являются ссылочными типами, поэтому можно считать, что строка также является объектом. Это эквивалентно передаче ссылки на объект «mimi» в name, поэтому теперь name указывает на «mimi». Таким образом, структура памяти на данный момент такая, как показано ниже:
Затем выполните код в теле конструктора:
это.имя=имя;
Здесь это относится к текущему объекту, который ссылается на кота в куче памяти. Здесь значение, содержащееся в имени в стеке, передается атрибуту имени объекта cat в памяти кучи, поэтому в это время значение, содержащееся в имени, также можно найти в строковом объекте «mimi», расположенном в В настоящее время это имя также является ссылочным объектом строкового объекта «mimi». По значению его атрибута можно найти строковый объект «mimi», расположенный в области данных. Распределение памяти в это время показано на рисунке ниже:
Затем выполните еще одну строку кода в теле метода:
идентификатор=сид++;
Здесь значение sid передается в id, поэтому значение id равно 100. После передачи sid прибавляем 1. В этот момент sid становится 101. Расположение памяти в данный момент показано на рисунке ниже.
В этот момент вызывается метод конструктора, и все пространство памяти, занятое локальными переменными, выделенными этому методу конструктора, исчезнет, поэтому память имен, расположенная в пространстве стека, исчезнет. Ссылка на строковый объект «mimi» в области данных в памяти стека также исчезает. В это время остается только ссылка на строковый объект «mimi» в динамической памяти. Структура памяти на данный момент такая, как показано ниже:
Следующее выполнение:
Кот пипи = новый кот("пипи"); Вот второй вызов метода-конструктора Cat(). Весь процесс вызова такой же, как и в первый раз. После завершения вызова расположение памяти в этот момент выглядит так, как показано на рисунке ниже:
Последние две строки кода печатаются путем вызова метода info(). Результаты печати следующие:
С помощью этой программы мы можем увидеть роль этой статической переменной-члена sid, которую можно посчитать. Всякий раз, когда появляется новый кот, дайте ему номер. Пусть он сам добавит 1.
После выполнения программы вся раскладка в памяти будет такой, как показано на рисунке выше. Продолжается до момента завершения вызова основного метода.
Здесь вызывается метод конструктора Cat(String name) для создания двух кошек. Сначала в памяти стека выделяются два небольших пространства, mimi и pipi, которые содержат адреса, по которым могут быть найдены два кота. по адресам в куче памяти. Две кошачьи цитаты. Метод построения здесь объявляет переменную строкового типа. Строковая константа размещается в области данных, поэтому переданные строки mimi и pipi будут храниться в области данных. Поэтому в области данных выделяются два небольших блока памяти для хранения строк mimi и pipi, которые содержат строки «mimi» и «pipi». Помимо четырех и восьми основных типов данных, строки также являются ссылочными типами. Все типы данных являются ссылочными типами. Таким образом, вы можете думать о строке как об объекте.
Вот два новых кота. Оба кота имеют свои собственные атрибуты id и name, поэтому id и name здесь являются нестатическими переменными-членами, то есть статических изменений нет. Таким образом, каждый раз, когда создается новый кот, этот новый кот имеет свой собственный идентификатор и имя, то есть нестатические переменные-члены id и name имеют отдельные копии для каждого объекта. Но для статических переменных-членов существует только одна копия. Независимо от того, сколько новых объектов, даже если новых объектов нет, статические переменные-члены сохранят одну копию в области данных. Как и здесь, sid хранится в области данных. Независимо от того, сколько новых котов находится в куче памяти, существует только одна копия sid, и только одна копия хранится в области данных.
Статические переменные-члены принадлежат всему классу, а не какому-то конкретному объекту. Итак, как получить доступ к значению этой статической переменной-члена? Прежде всего, любой объект может получить доступ к этому статическому значению и при доступе обращается к той же памяти. Второй момент заключается в том, что вы можете получить доступ к этому статическому значению, даже если объекта нет. Вы можете получить доступ к этому статическому значению через «имя класса.имя статической переменной-члена», поэтому в будущем вы увидите определенное имя класса плюс «. за которым следует Если есть что-то одно, то следующее должно быть статическим, например «System.out». Здесь доступ к этому выходу осуществляется через имя класса (системный класс) плюс «.», поэтому этот выход должен быть статическим.
Если член класса объявлен статическим, к нему можно получить доступ до создания любого объекта класса без необходимости ссылки на какой-либо объект. Самый распространенный пример статического члена — main(). Поскольку функция main() должна вызываться при начале выполнения программы, она объявлена статической.
Переменные, объявленные как статические, по сути являются глобальными переменными. При объявлении объекта копия статической переменной не создается, но все переменные экземпляра класса используют одну и ту же статическую переменную. Например: объявите счетчик статических переменных как счетчик новых экземпляров класса. Методы, объявленные статическими, имеют следующие ограничения:
(1) Они могут вызывать только другие статические методы.
(2) Они могут иметь доступ только к статическим данным.
(3) Они не могут каким-либо образом ссылаться на это или супер.
Если вам нужно инициализировать статические переменные посредством вычислений, вы можете объявить статический блок. Статический блок выполняется только один раз при загрузке класса. Пример ниже показывает
Класс имеет статический метод, несколько статических переменных и статический блок инициализации: public class UserStatic { static int a = 3; static int b; x); System.out.println("a = " + a); System.out.println("b = " + b } static { System.out.println("Статический блок); инициализирован."); b = a * 4; } public static void main(String args[]) { meth(42); } } После загрузки класса UseStatic выполняются все статические операторы. Сначала a присваивается значение 3, затем выполняется статический блок (печать сообщения) и, наконец, b инициализируется значением a*4 или 12. Затем вызывается main(), main() вызывает meth(), передавая значение 42 в x. Три оператора println() относятся к двум статическим переменным a и b и локальной переменной x.
Примечание. Ссылаться на какие-либо переменные экземпляра в статическом методе запрещено.
Вот вывод этой программы:
Статический блок инициализирован x = 42 a = 3 b = 12.
Статические методы и переменные можно использовать независимо от любого объекта вне класса, в котором они определены. В этом случае вам нужно только добавить оператор точку (.) после имени класса. Например, если вы хотите вызвать статический метод вне класса, вы можете использовать следующий общий формат:
имя класса.метод()
Здесь имя класса — это имя класса, в котором определен статический метод. Как видите, этот формат аналогичен формату вызова нестатических методов через переменные ссылки на объект. Доступ к статической переменной можно получить в том же формате — имя класса плюс оператор точки. Именно так Java реализует контролируемую версию глобальных функций и глобальных переменных.
Подведите итог:
(1) Статические члены не могут быть доступны экземплярам, созданным классом, в котором они расположены.
(2) Если члены без статической модификации являются членами объекта, они принадлежат каждому объекту.
(3) Члены, модифицированные с помощью static, являются членами класса, которые могут напрямую вызываться классом и являются общими для всех объектов.
Java Static: в качестве модификатора его можно использовать для изменения переменных, методов и блоков кода (но он не должен изменять классы).
(1) Измените переменные:
Свойство, общее для всех объектов класса, также называемое переменной класса. Это похоже на глобальные переменные в языке C. Переменные класса инициализируются при загрузке класса и инициализируются только один раз. Когда какой-либо объект в программе изменяет статическую переменную, другие объекты увидят измененное значение. Таким образом, переменные класса можно использовать в качестве счетчиков. Кроме того, доступ к статическим переменным Java можно получить напрямую, используя имя класса, не требуя объекта.
(2) Метод модификации:
Функция, общая для всех объектов класса, называется статическим методом. Доступ к статическим методам также можно получить напрямую, используя имя класса, не требуя объекта. Следовательно, к нестатическим переменным и нестатическим методам нельзя получить прямой доступ в статических методах, а такие ключевые слова, как this или super, не могут появляться в статических методах.
(3) Измените блоки кода Java:
Используйте static для изменения независимого блока кода в классе, который называется статическим блоком кода. Статические блоки кода выполняются при первой загрузке класса и только один раз. Статические блоки кода не имеют имен, поэтому их нельзя вызывать явно, а вызывают виртуальная машина только при загрузке класса. В основном он используется для выполнения некоторых операций инициализации.
(4) Давайте поговорим о загрузке классов:
Когда JVM впервые использует класс, она переходит по пути, указанному в пути к классам, чтобы найти файл байт-кода, соответствующий классу, прочитать его в JVM и сохранить. Этот процесс называется загрузкой класса.
Видно, что независимо от того, является ли это переменной, методом или блоком кода, если он модифицирован с помощью static, он будет «готов» при загрузке класса, то есть его можно будет использовать или уже выполнить. Все можно выполнить без объектов. Напротив, если статики нет, к ней нужно обращаться через объект.