1. Референтни променливи

В езика Java има два вида променливи: примитивни променливи и всичко останало. Както се случва, сега ще говорим за „всичко останало“.

Всъщност би било по-правилно да се каже, че има примитивни променливи и референтни променливи . И така, Howви са тези референтни променливи?

За разлика от примитивните типове, чиито променливи съхраняват стойности директно, референтните променливи съхраняват препратки към обекти. Тоест има обект някъде в паметта и референтната променлива просто съхранява address на този обект в паметта (препратка към обекта).

Само примитивните типове съхраняват стойности директно в променливи. Всички други типове съхраняват само препратка към обект . Между другото, вече сте се сблъсквали с два такива типа променливи - Stringпроменливи и променливи с масив .

Както масивът, така и низът са обекти, съхранявани някъде в паметта. Stringпроменливите и масивните променливи съхраняват само препратки към обекти.

Референтни променливи в Java

int a, int b and double dса примитивни променливи, които съхраняват своите стойности вътре в себе си.

Променливата String strе препратка и съхранява address (препратката) към Stringобект в паметта.

При присвояване на примитивна стойност на променлива от примитивен тип, нейната стойност се копира (дублира). При присвояване на референтна променлива се копира само addressът на обектасамият обект не се копира .


2. Какво представляват референциите?

Каква е фундаменталната разлика между референтните променливи и примитивните променливи?

Примитивната променлива е като кутия: можете да съхранявате няHowва стойност в нея. Референтната променлива е по-скоро като лист хартия с телефонен номер върху него.

Кола срещу ключове за кола

Представете си, че сте решor да подарите на приятел кола за рождения му ден. Няма да го увиете в кутия и да го носите със себе си: колата е твърде голяма за това.

Много по-удобно е да поднесете само ключовете за колата в достатъчно голяма кутия, за да ги поберете. Вашият приятел ще разбере всичко, когато извади ключовете от кутията. Няма нужда да носите цялата кола със себе си, когато можете просто да предадете ключовете.

Човек срещу нейния телефонен номер

Или ето още едно сравнение: човек и телефонният му номер. Телефонният номер не е лицето, но телефонният номер може да се използва, за да й се обадите, да я попитате за няHowва информация or да й дадете инструкции.

По същия начин препратката се използва за взаимодействие с обект. Всички обекти взаимодействат помежду си чрез препратки. Вместо да си "разменяме хора", просто си разменяме телефонни номера.

При присвояване на стойност на примитивна променлива, нейната стойност се копира (дублира). При присвояване на стойност на референтна променлива се копира само addressът (телефонният номер) на обекта — самият обект не се копира.

Препратката предлага още едно предимство: можете да предадете препратка към обект към няHowъв метод и методът ще може да модифицира (промени) обекта, като използва препратката към него, извиквайки неговите методи и осъществявайки достъп до данни в обекта.


3. Задаване на справки

При присвояване на референтни променливи се присвоява само addressът на обекта в паметта. Самите обекти не се появяват и не изчезват.

Този подход избягва копирането на големи количества памет. Ако трябва да предадете много голям обект към метод, ние просто предаваме препратката към обекта и това е всичко. Справката заема много по-малко място.

Възлагане на справки

Размерът на всички референтни променливи (независимо от техния тип) е еднакъв — 4 byteа (като int). Но! Ако вашето приложение работи на 64-битова Java машина, тогава всички препратки ще бъдат с размер 8 byteа (64 бита).

Нещо повече, препратките могат да се присвояват само една на друга. Не можете да променяте референции or да присвоявате произволни стойности на референтни променливи:

Код Описание
String hello = "Hello";
String s = hello;
Това е разрешено
String hello = "Hello";
hello++;
Но това не е позволено
String hello = 0x1234;
А това не е позволено

4. nullСправка

И Howво съхранява референтната променлива, ако все още нищо не й е присвоено?

Той съхранява нулева препратка. nullе специална ключова дума в Java, означаваща липсата на препратка (празна препратка). Стойността nullможе да бъде присвоена на всяка референтна променлива.

Всички референтни променливи са null, освен ако не им е присвоена няHowва референция.

Примери:

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


Променливата String nameима стойност по подразбиране: null.
Променливата int ageима стойност по подразбиране: 0.

Локалните променливи, на които не е присвоена стойност, се считат за неинициализирани Howто за примитивните, така и за референтните типове.

Ако променлива съхранява препратка към няHowъв обект и искате да изчистите стойността на променливата, тогава просто й присвоете нулева препратка.

Код Описание
String s = null;
s = "Hello";
s = null;
sмагазини null.
sсъхранява препратка към низов обект
sсъхранява null.

5. Предаване на препратки към методи

Ако даден метод има параметри, които са референтни типове , тогава стойностите се предават на метода по същия начин, Howто при работа с нереферентни променливи. На параметъра просто се присвоява стойността на другата променлива.

Пример:

Код Описание
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").

Ето How изглежда паметта преди извикване на fill метода:

Предаване на препратки към методи

Ето How изглежда паметта, когато fill методът се изпълнява :

Предаване на препратки към методи 2

Променливите dataи arrayсе отнасят до (съхраняват препратки към) същия контейнер в паметта.

Променливата valueсъхранява препратка към низовия обект ( "Hello").

Клетките на масива също само съхраняват препратки към "Hello"обекта.

Всъщност ниHowви обекти не се дублират - само препратките се копират.



6. Сравнение с езика C/C++

В интервюта понякога Java програмистите биват питани How данните се предават на методи в Java? И понякога въпросът е дали данните се предават по референция or по стойност?

Този въпрос идва от C++, но не е много смислен в Java . В Java на параметрите винаги се присвояват просто стойностите на аргументите. Така че правилният отговор би бил " по стойност ".

Но бъдете готови да обясните позицията си , тъй като може веднага да чуете репликата: "примитивните типове се предават по стойност, а референтните типове се предават по референция."

Този произход на този проблем произтича от факта, че много Java програмисти са бor C++ програмисти в миналото. В този език за програмиране въпросът How параметрите се предават на методите беше много важен.

В Java всичко е недвусмислено: примитивните типове съхраняват стойности и референтните типове също съхраняват стойност - референция. Въпросът е дали една променлива се счита за стойност .

В C++ една променлива може да съхранява Howто препратка към обект, така и самия обект. Същото важи и за примитивните типове: примитивна променлива може да съхранява стойност or да декларира променливата като препратка към int. Така че, за да избегнат объркване, C++ програмистите винаги се отнасят към обекта към референция като референция , а самия обект — като стойност.

В C++ можете лесно да имате ситуация, в която една променлива съдържа обект, но другата съдържа препратка към този обект. Съответно, въпросът Howво съхранява една променлива - самия обект or просто препратка към него - беше много важен. Когато даден обект е предаден на метод, той е копиран (ако е предаден по стойност) и не е копиран (ако е предаден чрез препратка).

В Java тази двойственост не съществува, така че правилният отговор е: аргументите се предават на методите на Java по стойност . Просто когато говорим за референтни променливи, тази стойност е референтна.