— Привет, бесплатный работник.
— Т.е. я хотел сказать «Здорова, Амиго». Хочу рассказать тебе о внутреннем устройстве переменных. Ты уже знаешь, что у каждой переменной есть область памяти, привязанная к ней, где эта переменная хранит своё значение.
— Ага. Ты рассказывал это в прошлый раз.
— Отлично. Хорошо, что ты это помнишь. Тогда продолжу.
— Все сложные типы состоят из более простых. Те, в свою очередь, из ещё более простых. Пока, наконец, дело не доходит до самых примитивных, неделимых типов. Их так и называют – примитивные типы. Например, int – это один из примитивных типов, а String – это уже сложный тип, хранящий свои данные в виде таблицы символов (где каждый символ — это примитивный тип — char).
— Очень интересно. Продолжай.
— Сложные типы образуются из простых путём группировки. Такие типы мы называем классами. Когда мы описываем в программе новый класс – это значит, что мы объявляем новый сложный составной тип, данные которого будут или другими сложными типами, или примитивными типами.
Код на Java | Описание |
---|---|
|
Объявили новый сложный тип – Person .Его данные – это переменная name типа String (сложный тип) и переменная age типа int (примитивный тип) |
|
Объявили новый сложный тип – Rectangle .Он состоит из четырёх переменных примитивного типа – int . |
|
Объявили новый сложный тип – Cat . У него есть переменные:— owner , сложный тип Person — territory , сложный тип Rectangle — age , примитивный тип int — name , сложный тип String |
— Всё пока ещё понятно, как ни странно.
— Т.к. большие (сложные) типы содержат в себе много маленьких (примитивных), то их объекты занимают много памяти. Больше, чем обычные переменные примитивных типов. Иногда намного больше. Присваивание таких переменных выполнялось очень долго и требовало копирования больших объёмов памяти. Поэтому переменные сложных типов хранят в себе не сам объект, а всего лишь ссылку на него! Т.е. четырёхбайтовый адрес. Этого хватает, чтобы можно было обращаться к данным этих объектов. Всю сложность, связанную с этим, берет на себя Java-машина.
— Ничего не понял.
— Мы уже говорили, что переменная – это как коробка. Если ты хочешь сохранить в ней число 13, то ты можешь написать его на листе и положить в коробку.
— Но представь, что тебе надо сохранить в коробку (переменную) что-нибудь побольше. Например, собаку, машину или твоего соседа Васю. Чтобы не пихать в коробку невпихиваемое, можно поступить проще: вместо собаки взять ее фото, вместо машины – ее номер, вместо Васи – его номер телефона.
— Вот мы берем лист бумаги и пишем на нем телефонный номер Васи. Это и будет аналогом ссылки на объект. Если мы достанем из коробки лист с номером Васи, отксерим его и положим в несколько коробок, то количество ссылок на Васю увеличится, но Вася как был один, так и остался. Что, в общем-то, логично.
— Особенность такого хранения данных в том, что ссылок может быть много, а объект – один.
— Очень интересно. Почти понял, кстати. Ответь только еще раз: что будет, если я одной переменной сложного типа присвою другую переменную сложного типа?
— Тогда эти две переменные будут содержать одинаковые адреса. И, значит, изменение данных, хранящихся в одной переменой сложного типа, приведёт к изменению данных, хранящихся в другой. Объект-то, на который они хранят ссылки, реально всего один. А переменных, хранящих на него ссылки, может быть очень много.
— А что хранится в переменных сложных (ссылочных/классовых) типов, пока там ещё нет ссылки на объект? Такое вообще может быть?
— Да, Амиго. Ты опередил меня своим вопросом. Такое может быть. Если в переменной ссылочного (сложного) типа ещё нет ссылки на какой-то объект, то она хранит null – специальную «пустую ссылку». На самом деле, она просто хранит адрес объекта равный 0. Но Java-машина никогда не создаёт объекты с таким адресом, и поэтому всегда знает, что если переменная-ссылка содержит 0, то никакого объекта там нет.
Код на Java | Описание |
---|---|
|
Эквивалентные записи. |
|
Создали переменную person, её значение null. Занесли в неё адрес новосозданного объекта. Присвоили переменной ссылку null. |
|
Создали объект Cat, занесли его ссылку в переменную cat. cat.owner равен null. Занесли в cat.owner ссылку на новосозданный объект Person. cat.owner.name пока ещё null. cat.owner.name присвоили имя – God. |
— Я правильно понял? Переменные делятся на два типа: примитивные и ссылочные. Примитивные типы у себя внутри хранят значение, а ссылочные – ссылку на объект. Примитивные типы – это int, char, boolean и ещё немного, а ссылочные типы – это все остальные, и образуются они с помощью классов.
— Абсолютно верно, мальчик мой.
— Раз ты все понял, вот тебе задачи на закрепление материала.