JavaRush /Курсы /Java Syntax Pro /Переменные-ссылки в Java

Переменные-ссылки в Java

Java Syntax Pro
7 уровень , 2 лекция
Открыта

1. Переменные-ссылки

В языке Java переменные могут быть двух видов: переменные примитивного типа и все остальные. Вот про «все остальные» мы сейчас и поговорим.

На самом деле правильнее будет сказать, что есть переменные примитивного типа (primitive type variables) и ссылочные переменные (reference variables). Так что же это такое, эти ссылочные переменные?

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

Значения прямо внутри переменных хранят только примитивные типы, все остальные типы хранят только ссылку на объект. Ранее вы уже, кстати, сталкивались с двумя такими типами переменных — это переменные типа String и переменные типа массив.

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

Переменные int a, int b и double d — примитивные и хранят значение внутри себя.

Переменная String str — ссылочная и хранит адрес (ссылку) объекта типа String в памяти.

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


2. Суть ссылок

В чем принципиальное отличие переменных-ссылок от примитивных переменных?

Примитивная переменная — как коробка: в ней можно хранить какое-нибудь значение. Переменная-ссылка больше похожа на листок бумаги с телефонным номером на нем.

Машина vs ключи от машины

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

Гораздо удобнее взять с собой только ключи от машины и коробку, достаточно вместительную для них. А ваш друг и так все поймет, когда достанет из коробки ключи. Нет нужды нести с собой всю машину, когда можно просто передать ключи.

Человек vs его телефонный номер

Или еще один вариант: человек и его телефонный номер. Телефонный номер — не сам человек, но номер телефона можно использовать, чтобы звонить ему, спрашивать у него какую-то информацию, давать команды.

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

При присваивании значения в примитивную переменную, его значение копируется (дублируется). При присваивании же значения ссылочной переменной копируется только адрес объекта («телефонный номер»), сам же объект при этом не копируется.

Ссылка даёт ещё одно преимущество: можно передать ссылку на объект в какой-нибудь метод, и этот метод будет в состоянии модифицировать (изменять) наш объект, используя ссылку на него, вызывая его методы и обращаясь к данным внутри объекта.


3. Присваивание ссылок

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

Такой подход позволяет избежать копирования больших объемов памяти. Если куда-то нужно передать очень большой объект, мы просто передадим в этот метод ссылку на объект и все. Ссылка занимает гораздо меньше места.

Присваивание ссылок

Размер всех переменных-ссылок (независимо от типа) одинаков и составляет 4 байта (как тип int). Но! Если ваше приложение запущено на 64-х разрядной Java-машине, размер всех ссылок будет 8 байт (64 бита).

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

Код Описание
String hello = "Привет";
String s = hello;
Так можно
String hello = "Привет";
hello++;
А так — нельзя
String hello = 0x1234;
И так — нельзя

4. Пустая ссылка — null

А что хранит переменная-ссылка, если ей еще ничего не присвоили?

А хранит она пустую ссылку — null. null — это специальное ключевое слово в Java, обозначающее отсутствие ссылки (пустую ссылку). Значение null можно присвоить любой ссылочной переменной.

Все переменные-ссылки, если им не присвоена какая-нибудь ссылка, имеют значение null.

Примеры:

Код Описание
class Person
{
   public static String name;
   public static int age;
}


Переменная String name имеет значение по умолчанию: null.
Переменная int age имеет значение по умолчанию: 0.

Локальные переменные без значения считаются неинициализированными как для примитивных типов, так и для типов-ссылок.

Если переменная хранит ссылку на какой-то объект, а вы хотите стереть значение переменной, просто присвойте ей ссылку null.

Код Описание
String s = null;
s = "Привет";
s = null;
s хранит ссылку null.
s хранит ссылку на объект-строку
s хранит ссылку null

5. Передача ссылок в методы

Если у какого-нибудь метода есть параметры ссылочные переменные, передача значений в них происходит точно так же, как и при работе с обычными переменными. Переменной-параметру просто присваивается значение другой переменной.

Пример:

Код Описание
class Solution
{
   public static void fill(String[] array, String value)
   {
      for (int i = 0; i < array.length; i++)
        array[i] = value;
   }

   public static void main(String[] args)
   {
     String[] data = new String[10];
     fill(data, "Hello");
   }
}


Метод fill заполняет переданный массив array переданным значением value.

При вызове метода fill переменной array присваивается ссылка на массив data. Переменной value присваивается ссылка на объект-строку «Hello».

Вот как будет выглядеть ситуация в памяти перед вызовом метода fill:

Передача ссылок в методы

Вот как будет выглядеть ситуация во время работы метода fill:

Передача ссылок в методы 2

Переменные data и array ссылаются (хранят ссылки) на один и тот же массив-контейнер в памяти.

Переменная value хранит ссылку объекта строки Hello.

Ячейки массива тоже хранят просто ссылки на объект Hello.

Фактически никакого дублирования объектов не происходит — копируются только ссылки.



6. Сравнение с языком С/С++

Иногда Java-программистов спрашивают на собеседовании: как передаются данные в методы в Java? Иногда еще уточняют: по ссылке или по значению?

Этот вопрос идет из языка С++ — в языке Java он не имеет смысла. В Java переменным-параметрам всегда просто присваиваются значения переменных-аргументов. Так что правильным ответом будет — по значению.

Но будьте готовы к тому, чтобы объяснить свою позицию, т.к. вам могут тут же возразить, что «примитивные типы передаются по значению, а ссылочные – по ссылке».

Истоки этой проблемы связаны с тем, что многие Java-программисты были в прошлом С++ программистами. А там вопрос «как передаются параметры в методы» играл очень важную роль.

В Java все однозначно: примитивные типы хранят значения, ссылочные тоже хранят значение — ссылку. Все дело в том, что считать значением переменной.

В языке C++ в переменной можно было хранить как ссылку на объект, так и сам объект. То же касалось примитивных типов: в переменной можно было хранить значение или объявить переменную ссылкой на тип int. Поэтому чтобы не путаться, С++ программисты ссылку на объект всегда называют ссылкой, а сам объект — значением.

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

В Java этой двойственности нет, и правильный ответ звучит так: параметры в методы Java передаются по значению. Просто в случае с ссылочными переменными это значение — ссылка.

Комментарии (246)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Grigoryvvv Уровень 10 Expert
25 сентября 2025
25.09.2025 / 8 уровень
Gris Hiver Уровень 1
4 августа 2025
Спасибо за раздел сравнения с языком С/С++ ! Меня долго эта "ссылка" вводила в заблуждение)
Дмитрий Уровень 14
15 июля 2025
поэксперементировал с примером из лекции. мне показалось что эта информация может быть интересной. String hello = "Привет"; String s = hello; System.out.println(hello.hashCode()); // одинаковый адрес System.out.println(s.hashCode()); //одинаковый адрес hello=null; //одНУЛЛилась только ССЫЛКА от hello на "Привет" // System.out.println(hello.hashCode()); вызовет исключение System.out.println(s.hashCode()); // одинаковый адрес System.out.println(s); // выведется "Привет".
Katakuri Charlotte Уровень 14
8 октября 2025
hashCode это не адрес, это вычисление по содержимому строки. Даже если мы будем иметь 2 переменные, которые будут ссылаться на разные объекты, но содержание этих объектов будет одинаковым - будем получать одинаковый hashCode:

String str1 = new String("Hello");
String str2 = new String("Hello");

System.out.println(str1.hashCode() == str2.hashCode()); // true 
System.out.println(str1 == str2);                       // false 
Насчет назначения переменной null: когда ты обнуляешь hello, то ты обнуляешь только ссылку, а не сам объект (если бы на объект больше не было ссылок, то объект бы удалился), но так как на него ссылается вторая ссылка s то объект "Привет" продолжает жить в программе

String hello = "Hello";
String hi = hello;

hello = null; // обнулили ссылку на объект "Hello"
             // но объект не удаляется, hi до сих пор ссылается на этот объект

Руслан Уровень 46
9 июля 2025
Очень хорошая лекция поставьте лайк плз
REK.QA Уровень 4
20 июня 2025
А может в Идее первая задача не компилироваться, а на сайте пройти проверку?
Anonymous #3585174 Уровень 33
8 июня 2025
like
Владимир Уровень 40
12 мая 2025
Очень крутая лекция! Объяснение про работу ссылочных типов с памятью - 12 из 10! Спасибо за такой крутой и наглядный материал❤️
Anand Уровень 32
15 апреля 2025
Очень хорошо и понятно написано, молодцы
xiokrius Уровень 32
8 апреля 2025
8 уровень, идём дальше
Atmanant Уровень 15
3 февраля 2025
Прошу прощения если уже было (не все комменты просмотрел), но т.к. уже решил и возник ещё один вариант решения интересно узнать: будет ли засчитано правильным если решить задачу по заполнению массива (последние две в данной лекции) через "Arrays.fill()"???
Anonymous #3551727 Уровень 30
8 февраля 2025
да
17 марта 2025
Там так и надо