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 біти).
Посилання при цьому можна тільки присвоювати один одному. Ви не можете міняти посилання або присвоювати їм довільні значення:
| Код | Опис |
|---|---|
|
Так можна |
|
А так — не можна |
|
І так — не можна |
4. Порожнє посилання — null
А що зберігає змінна-посилання, якщо їй ще нічого не присвоїли?
А зберігає вона порожнє посилання — null. null — це спеціальне ключове слово в Java, яке означає відсутність посилання (порожнє посилання). Значення null можна присвоїти будь-якій посилальній змінній.
Усі змінні-посилання, якщо їм не присвоєно якесь посилання, мають значення null.
Приклади:
| Код | Опис |
|---|---|
|
Змінна String name має значення за замовчуванням: null.Змінна int age має значення за замовчуванням: 0. |
Локальні змінні без значення вважаються неініціалізованими як для примітивних типів, так і для типів-посилань.
Якщо змінна зберігає посилання на якийсь об'єкт, а ви хочете стерти значення змінної, просто присвойте їй посилання null.
| Код | Опис |
|---|---|
|
s зберігає посилання null.s зберігає посилання на об'єкт-рядокs зберігає посилання null |
5. Передача посилань у методи
Якщо у якогось методу є параметри посилальні змінні, передача значень у них відбувається так само, як і при роботі зі звичайними змінними. Змінній-параметру просто присвоюється значення іншої змінної.
Приклад:
| Код | Опис |
|---|---|
|
Метод fill заповнює переданий масив array переданим значенням value. |
При виклику методу fill змінній array присвоюється посилання на масив data. Змінній value присвоюється посилання на об'єкт-рядок «Hello».
От як виглядатиме ситуація в пам'яті перед викликом методу fill:

От як виглядатиме ситуація під час роботи методу fill:
Змінні data і array посилаються (зберігають посилання) на один і той самий масив-контейнер у пам'яті.
Змінна value зберігає посилання об'єкта рядки Hello.
Клітинки масиву теж зберігають просто посилання на об'єкт Hello.
Фактично ніякого дублювання об'єктів не відбувається — копіюються тільки посилання.
6. Порівняння з мовою C/C++
Іноді Java-програмістів запитують на співбесіді: як передаються дані в методи у Java? Іноді ще уточнюють: по посиланню чи за значенням?
Це питання йде з мови C++ — у мові Java він не має сенсу. У Java змінним-параметрам завжди просто присвоюються значення змінних-аргументів. Тому правильна відповідь буде — за значенням.
Але будьте готові до того, щоб пояснити свою позицію, адже вам можуть тут же заперечити, що «примітивні типи передаються за значенням, а посилальні – по посиланню».
Коріння цієї проблеми пов'язані з тим, що багато Java-програмістів були в минулому програмістами C++. А там питання «як передаються параметри в методи» грало дуже важливу роль.
У Java все однозначно: примітивні типи зберігають значення, посилальні теж зберігають значення — посилання. Все залежить від того, що вважати значенням змінної.
У мові C++ у змінній можна було зберігати як посилання на об'єкт, так і сам об'єкт. Те ж стосувалося примітивних типів: у змінній можна було зберігати значення або оголосити змінну посиланням на тип int. Тому, щоб не плутатися, C++ програмісти посилання на об'єкт завжди називають посиланням, а сам об'єкт — значенням.
У C++ легко могла скластися ситуація, коли одна змінна містить об'єкт, а інша — посилання на цей самий об'єкт. Тому питання, що зберігає в собі змінна — сам об'єкт або тільки посилання на нього — було дуже важливим. При передачі в метод об'єкта він копіювався (якщо передавався за значенням), і не копіювався (якщо передавався по посиланню).
У Java цієї подвійності немає, і правильна відповідь звучить так: параметри в методи Java передаються за значенням. Просто у випадку з посилальними змінними це значення — посилання.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ