Отличие примитивных типов от ссылочных java

Типы данных

— Т.е. я хотел сказать «Здорова, Амиго». Хочу рассказать тебе о внутреннем устройстве переменных. Ты уже знаешь, что у каждой переменной есть область памяти, привязанная к ней, где эта переменная хранит своё значение.

— Ага. Ты рассказывал это в прошлый раз.

— Отлично. Хорошо, что ты это помнишь. Тогда продолжу.

— Все сложные типы состоят из более простых. Те, в свою очередь, из ещё более простых. Пока, наконец, дело не доходит до самых примитивных, неделимых типов. Их так и называют – примитивные типы. Например, int – это один из примитивных типов, а String – это уже сложный тип, хранящий свои данные в виде таблицы символов (где каждый символ — это примитивный тип — char).

— Очень интересно. Продолжай.

— Сложные типы образуются из простых путём группировки. Такие типы мы называем классами . Когда мы описываем в программе новый класс – это значит, что мы объявляем новый сложный составной тип , данные которого будут или другими сложными типами, или примитивными типами.

public class Person < String name; int age; >
public class Rectangle < int x, y, width, height; >
public class Cat < Person owner; Rectangle territory; int age; String name; >

— Всё пока ещё понятно, как ни странно.

— Т.к. большие (сложные) типы содержат в себе много маленьких (примитивных), то их объекты занимают много памяти. Больше, чем обычные переменные примитивных типов. Иногда намного больше. Присваивание таких переменных выполнялось очень долго и требовало копирования больших объёмов памяти. Поэтому переменные сложных типов хранят в себе не сам объект, а всего лишь ссылку на него! Т.е. четырёхбайтовый адрес. Этого хватает, чтобы можно было обращаться к данным этих объектов. Всю сложность, связанную с этим, берет на себя Java-машина.

Читайте также:  Change list items python

— Мы уже говорили, что переменная – это как коробка. Если ты хочешь сохранить в ней число 13, то ты можешь написать его на листе и положить в коробку.

— Но представь, что тебе надо сохранить в коробку (переменную) что-нибудь побольше. Например, собаку, машину или твоего соседа Васю. Чтобы не пихать в коробку невпихиваемое, можно поступить проще: вместо собаки взять ее фото, вместо машины – ее номер, вместо Васи – его номер телефона.

— Вот мы берем лист бумаги и пишем на нем телефонный номер Васи. Это и будет аналогом ссылки на объект. Если мы достанем из коробки лист с номером Васи, отксерим его и положим в несколько коробок, то количество ссылок на Васю увеличится, но Вася как был один, так и остался. Что, в общем-то, логично.

— Особенность такого хранения данных в том, что ссылок может быть много, а объект – один.

— Очень интересно. Почти понял, кстати. Ответь только еще раз: что будет, если я одной переменной сложного типа присвою другую переменную сложного типа?

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

— А что хранится в переменных сложных (ссылочных/классовых) типов, пока там ещё нет ссылки на объект? Такое вообще может быть?

— Да, Амиго. Ты опередил меня своим вопросом. Такое может быть. Если в переменной ссылочного (сложного) типа ещё нет ссылки на какой-то объект, то она хранит null – специальную «пустую ссылку». На самом деле, она просто хранит адрес объекта равный 0. Но Java-машина никогда не создаёт объекты с таким адресом, и поэтому всегда знает, что если переменная-ссылка содержит 0, то никакого объекта там нет.

Person person; person = new Person(); person = null;
Cat cat = new Cat(); cat.owner = new Person(); cat.owner.name = "God";

— Я правильно понял? Переменные делятся на два типа: примитивные и ссылочные. Примитивные типы у себя внутри хранят значение, а ссылочные – ссылку на объект. Примитивные типы – это int, char, boolean и ещё немного, а ссылочные типы – это все остальные, и образуются они с помощью классов.

— Абсолютно верно, мальчик мой.

— Раз ты все понял, вот тебе задачи на закрепление материала.

Источник

Типы данных Java: примитивные, ссылочные

Каждая переменная в Java имеет тип данных, которые разделены на две группы:

Переменная занимает некоторое место в памяти в зависимости от ее типа данных.

Примитив содержит значение переменной непосредственно в памяти, выделенной для нее. Например, число или символ.

Ссылочный типа отличается еще называется ссылкой. Не содержит объект, но содержит ссылку на него, которая указывает на другое место в памяти, где он хранится. Через такую ссылку можете получить доступ к полям и методам ссылочного объекта. Допустимо иметь много разных переменных, ссылающихся на один и тот же объект. Это невозможно с примитивами.

Примитивные типы данных

Тип Значение
boolean Двоичное true или false
byte 8-битное со знаком, значения от -128 до 127
short 16-битное со знаком, значения от -32,768 до 32,767
char 16-битный символ юникода
int 32-битное со знаком, значения от -2.147.483.648 до 2.147.483.647
long 64-битное со знаком, значения от -9,223.372.036.854.775.808 до 9.223.372.036.854.775.808
float 32-разрядное с плавающей запятой
double 64-битное с плавающей запятой

Примитивные типы данных не являются ни объектами, ни ссылками на них.

Типы объектов

Примитивные типы также входят в версии, которые являются полноценными объектами. Это означает, что можно:

  • ссылаться на них через ссылку на объект;
  • давать несколько ссылок на одно и то же значение;
  • вызывать методы для них, как и для любого другого объекта.
Формат Описание
Boolean A binary value of either true or false
Byte 8 bit signed value, values from -128 to 127
Short 16 bit signed value, values from -32.768 to 32.767
Character 16 bit Unicode character
Integer 32 bit signed value, values from -2.147.483.648 to 2.147.483.647
Long 64 bit signed value, values from -9.223.372.036.854.775.808 to 9.223.372.036.854.775.808
Float 32 bit floating point value
Double 64 bit floating point value
String N byte Unicode string of textual data. Immutable

Обратите внимание, что типы объектов пишутся с заглавной буквы в начале их имени. Примитивная версия (иной вариант) пишется всеми строчными буквами. Существуют также различия в аббревиатурах, такие как int против Integer и char против Character.

Также можете создавать свои собственные более сложные типы данных, классы.

Когда объявляете переменную ссылки, она не указывает ни на один из них, т.к. сначала нужно создать (экземпляр) его. Вот как это делается:

Integer myInteger; myInteger = new Integer(45);

В этом примере переменная myInteger ссылается на объект Integer, который внутренне содержит 45. Именно новая часть Integer(45) кода создает Integer.

Создание при объявленной переменной:

Integer myInteger = new Integer(45);

Версии объектов примитивных типов данных неизменны

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

Переменная, которая ссылается на объект, может быть указана на другой. Вот пример:

Integer myInteger = new Integer(45); myInteger = new Integer(33);

Автобокс

До Java 5 вам приходилось вызывать методы для объектных примитивных типов, чтобы получить их значение:

Integer myInteger = new Integer(45); int myInt = myInteger.intValue();

С Java 5 у вас есть понятие, называемое «автобокс». Это означает, что оболочка может автоматически «упаковывать» примитивную переменную в объектную версию или «распаковывать» объектный примитив. В зависимости от того, что требуется. Предыдущий пример может быть написан так:

Integer myInteger = new Integer(45); int myInt = myInteger;

В этом случае Java автоматически извлечет int из myInteger и присвоит это значение myInt.

Точно так же создание объектной примитивной переменной было ручным действием:

int myInt = 45; Integer myInteger = new Integer(myInt);

С помощью автобокса оболочка может сделать это за вас. Теперь запись выглядит так:

int myInt = 45; Integer myInteger = myInt;

Затем Java автоматически «упаковывает» примитив в объектную версию соответствующего типа.

Функции автобокса позволяют использовать примитивы, для которых обычно требовалась его объектная версия и наоборот. Есть одна ловушка. Переменная object (ссылка) может указывать на ноль, то есть на ничто. Если попытаетесь преобразовать ноль в примитивное значение, получите исключение NullPointerException (ошибка, которая приводит к сбою программы). Этот код показывает пример этого:

Integer myInteger = null; int myInt = myInteger;

Этот код будет хорошо скомпилирован, но при выполнении он приведет к исключению NullPointerException, поскольку myInteger указывает на ноль. Таким образом, невозможно преобразовать (распаковать) значение объекта, на который он указывает, поскольку не указывает ни на один объект.

Источник

Передача параметров в Java

Java-университет

Переменная в Java — это контейнер, со значением в нем. Так что значит «передать» переменную? И какова разница между примитивными и ссылочными типами данных.

Передача параметров в Java - 1

В строке 1 создается переменная x типа int и ей присваивается значение 3. В строке 2, создается переменная y типа int и ей присвается значение переменной x. В дальнейшем переменная x никак не влияет на y. Java копирует значение х (3) и помещает эту копию в у. Это передача параметра по значению. Вы не записываете одну переменную в другую. Значение копируется и присваивается новой переменной. Выражение у = х; НЕ означает «записать x в y«. Оно означает «скопировать значение внутри х и записать эту копию в у«. Если позже я изменю y:

Повлияет ли это на x? Конечно нет. x по прежнему имеет значение 3. Если позже я изменю х:

Как это отразится на y? Никак. Они никак не связаны после того, как было сделано присвоение (КОПИРОВАНИЕ значения). А что насчет ссылочных типов? Как они работают? Не так уж сложно, на самом деле это правило то же самое. Ссылки делают тоже самое — вы получаете копию ссылки. Так что, если я говорю:

Ссылка А копируется в ссылку B. К объекту это не относится — у вас по прежнему всего один объект. Но теперь у вас есть две различных ссылки, контролирующие один и тот же объект Cat. Теперь давайте рассмотрим передачу параметров в методы. Java передает параметры по значению. Всегда. Это означает — «скопировать значение и передать копию.» Для примитивных типов это легко:

 int х = 5; doStuff (х); / / Передать копию х (значение 5) в метод doStuff 

Копия значения x, тоесть 5, передается в метод doStuff (). Метод doStuff () имеет свою собственную переменную, которая называется y. Переменная y — новая, другая переменная. С копией того, что было в х на момент передачи его в метод. С этого момента, у и х не влияют друг на друга. При изменении у, вы не затрагиваете х.

И наоборот — при изменении х, вы не измените y. Единственное что сделал x в этом деле это скопировал свое значение и передал его в метод doStuff(). Как «передача по значению» работает со ссылками? Слишком многие люди говорят, «Java передает примитивные типы по значению, а объекты по ссылке». Это не так как говорят. Java передает все по значению. С примитивами, вы получаете копию содержимого. Со ссылками вы тоже получаете копию содержимого. Но что такое содержимое ссылки? Пульт дистанционного управления. Средства для управления / доступа к объекту. Когда вы передаете ссылку на объект в метод, вы передаете копию ссылки. Клон пульта дистанционного управления. Объект все еще сидит в куче где был создан, ожидая кого-то, чтобы использовали пульт. Объект не волнует сколько пультов «запрограммированы» чтобы контролировать его. Это волнует только сборщика мусора и вас, программиста. Поэтому, когда вы говорите:

 Cat A = new Cat (); doStuff (А); void doStuff (Cat B) < / / Использование B >

Существует только один объект Cat. Но теперь два пульта управления (ссылки) могут получить доступ к одному и тому же объекту Cat. Так что теперь все, что B делает объекту Cat, повлияет на Cat, на который указывает A, но это не повлияет на содержимое A! Вы можете изменить Cat, используя новую ссылку B (скопированную непосредственно с А), но вы не можете изменить А. Какого черта это значит? Вы можете изменить объект, на который ссылается А, но вы не можете взять и изменить ссылку А — переадресовать её на другой объект или null. Так что если вы измените ссылку B (не сам объект Cat на который ссылается B, а само значение ссылки) вы не измените значение А. И наоборот. Так что:

 Cat A = new Cat (); doStuff (А); void doStuff (Cat B) < B = new Cat (); / / Не повлияет на ссылку A >

Это просто значит, что B указывает на другой объект. A по-прежнему счастлива. Так что повторяйте за мной: Java передает все по значению. (Хорошо, еще раз. с чувством.) Java передает все по значению. Для примитивных типов — вы передаете копию текущего значения, для ссылок на объекты — вы передаете копию ссылки (дистанционного управления). Вы никогда не передаете объект. Все объекты хранятся в куче. Всегда. Теперь заварите здоровенную чашку кофе и пишите код! Оригинал статьи.

Источник

Оцените статью