Мы еще раз пройдемся по примитивным типам. Примитивные типы часто имеют простую структуру, такую ​​как одна буква или одно целое число. В основном мы сотрудничаем с ними, чтобы выполнить задачу как можно быстрее. Обычно они занимают мало памяти и многочисленны в программах. Их принято называть «легкими» зданиями. Каждая из них имеет определенный размер. Целое число, число с плавающей запятой, двойное число, символ, логическое значение и другие типы значений являются примерами.

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

Объем оперативной памяти, который может потреблять наше приложение, показан на изображении выше. В программе создана переменная с типом данных int. Он был помещен прямо в стек и имеет значение 56. Пример соответствующего кода может быть следующим:

Вы можете видеть его как переменную с назначенной областью памяти, созданной в стеке, которая имеет размер 32 бита и содержит число 56.

Создайте новую консольную программу и добавьте в нее простой класс для представления «пользователей». Мы удалим комментарии и пропустим модификаторы доступа для простоты:

Пользователи могут быть легко распечатаны благодаря двум простым общедоступным полям класса, конструктору и переопределенному методу toString(). Давайте создадим экземпляр класса в нашей основной программе:

Ссылочный тип данных теперь присутствует в переменной u. Посмотрим, как это обстоятельство фигурирует в наших воспоминаниях:

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

Оперативная память содержит кучу и стек. Доступность и размер имеют значение. Куча имеет практически безграничную память, но до нее трудно добраться, что делает ее в целом медленнее. Память стека, с другой стороны, быстрая, но имеет небольшую емкость.

На самом деле переменные ссылочного типа сохраняются в памяти дважды — один раз в куче и один раз в стеке.

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

ПРИМЕЧАНИЕ. Существует существенное различие между указателями и ссылками, например, в C++. К счастью, в Java не используются указатели, а объекты просто называются «ссылками», что, как ни странно, имеет больше общего с указателями C++, чем с указателями Java. Используемый здесь термин «ссылка» относится к справочнику по Java, а не к справочнику по C++.

Существуют различные обоснования этой практики, в том числе:

  1. Существует максимальный размер стека.

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

3. Ссылки позволяют нам легко проектировать структуры с динамическими размерами, такие как структуры, подобные массивам, которые позволяют добавлять дополнительные элементы во время выполнения. Эти компоненты действуют как последовательность объектов, которые связаны друг с другом.

Теперь давайте объявим две переменные типа int и две переменные пользовательского типа:

Вот как это будет выглядеть в памяти:

Давайте теперь свяжем переменную b с переменной a. Кроме того, мы свяжем переменную v с переменной u. Примитивные типы просто копируются в стек при присвоении значений. В качестве альтернативы, когда речь идет об объектах, реплицируется только ссылка на объект (который на самом деле тоже является примитивным типом). Нет новых объектов, созданных путем присвоения ссылок. Теперь наш код должен выглядеть так:

С точки зрения памяти это будет выглядеть так:

Теперь давайте проверим механизм ссылок, чтобы убедиться, что он работает должным образом: сначала будут напечатаны все четыре переменные как до, так и после переназначения. Мы могли бы создать метод для печати, но для более важных задач нам нужны классы, и я еще не научил вас, как определять методы в ArenaFight.java (файл, содержащий функцию main()). Теперь изменим код:

Мы до сих пор не можем сказать, в чем разница между примитивными и эталонными типами данных на основе вывода:

Однако мы знаем, что u и v представляют один и тот же элемент, но на самом деле a и b — два разных целых числа с одинаковым значением. Основываясь на том, что мы знаем, давайте изменим имя пользователя v, и новое имя должно быть отражено в переменной u:

Мы изменили объект в переменной v. Теперь давайте напечатаем u и v еще раз:

Поскольку обе переменные ссылаются на один и тот же объект, пользователь u изменяется вместе с переменной v. Самый простой способ создать точную копию объекта — воссоздать его с помощью конструктора и инициализировать новый объект теми же данными, что и исходный. Объекты также можно дублировать, но мы обсудим это позже. Возвращаясь к Джеймсу Брауну:

Что теперь с ним будет, спросите вы? Его «съест» то, что мы называем сборщиком мусора.

ИСПОЛЬЗОВАННАЯ ЛИТЕРАТУРА

  1. https://docs.oracle.com/en/java/javase/19/ (дополнительная информация о JAVA и типах)
  2. https://dev.java/learn/ (для изучения JAVA это хороший ресурс.)