1. Сравнения

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

Целите числа се сравняват много лесно – просто ги използвате ==и сте готови. За да сравните реални числа , трябва да сравните тяхната разлика (or по-скоро абсолютната стойност на разликата) с няHowво много малко число.

Сравняването на низове е още по-трудно. Преди всичко това е така, защото низовете са обекти. Нещо повече, програмистите често искат сравнението на низове да върви малко по-различно в зависимост от ситуацията.


2. Как са подредени низовете в паметта

Както вече видяхте, низовете се съхраняват в паметта по различен начин от целите и реалните числа:

Как низовете са подредени в паметта

Два блока памет се използват за съхраняване на низове: единият блок съхранява самия текст (размерът му зависи от размера на текста), докато вторият блок (4 byteа) съхранява address на първия блок.

Въпреки че опитен програмист би казал нещо като „ String strпроменливата съхранява препратка към Stringобект.


3. Присвояване на препратки към низ

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

String text = "This is a very important message";
String message = text;

И ето Howво ще съдържа паметта като резултат:

Присвояване на препратки към низ

След този тип операция на присвояване, Stringобектът остава там, където е бил, и само неговият address (препратка към обекта) се копира в променливата message.


4. Работа с препратки и обекти

Но ако решите да преобразувате низ в главни букви (главни букви), Java машината прави всичко Howто трябва: ще получите два Stringобекта, а променливите textи messageще съхраняват препратки, всеки към свой собствен обект.

Пример:

String text = "This is a very important message";
String message = text.toUpperCase(); 

И ето Howво ще съдържа паметта като резултат:

Работа с препратки и обекти

Моля, обърнете внимание, че toUpperCase()методът не променя низа, към който е извикан. Вместо това той създава нов низ (нов обект) и връща препратка към него.

Какво ще кажете за още по-интересен пример. Да приемем, че решите да предадете низ към Scannerобект (така че той да чете стойности от низа).

Пример:

String text = "10 20 40 80";
Scanner console = new Scanner(text);
int a = console.nextInt();
int b = console.nextInt();

Можете да научите повече за това How Scannerработи класът тук .

Ето How всичко ще бъде съхранено в паметта:

Работа с препратки и обекти.  Клас скенер

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


5. Сравняване на препратки към Stringобекти

И накрая, стигнахме до забавната част: сравнение на низове.

Има два оператора, които можете да използвате за сравняване на низови променливи: ==(равно) и !=(не е равно). Не можете да използвате операторите „по-голямо от“, „по-малко от“ or „по-голямо от or равно на“ — компилаторът няма да го позволи.

Но тук има един интересен нюанс: Howво всъщност се съхранява в низови променливи? Точно така: addressи (препратки) към обекти. И точно тези addressи ще бъдат сравнени:

String text = "Hi";
String message = text;
String s1 = text.toUpperCase();
String s2 = text.toUpperCase(); 

Ето Howво ще остане в паметта:

Сравняване на препратки към String обекти

Променливите messageи textсе отнасят до (съхраняват address на) един и същ обект. Но променливите s1и s2съхраняват препратки към обекти, които са много сходни, но различни.

И ако сравните тези 4 променливи в codeа, ще получите следния резултат:

Код Конзолен изход
String text = "Hi";
String message = text;
String s1 = text.toUpperCase();
String s2 = text.toUpperCase();
System.out.println(text == message);
System.out.println(text == s1);
System.out.println(s1 == s2); 


true  // The addresses are equal
false // The addresses are different
false // The addresses are different