1. Porównania

Bardzo często programista musi porównywać ze sobą różne zmienne. I jak już widzieliście, nie wszystko jest takie proste.

Liczby całkowite są bardzo łatwe do porównania - po prostu go użyj ==i to wszystko. Aby porównać liczby rzeczywiste , musisz już porównać ich różnicę (a raczej moduł różnicy) z jakąś bardzo małą liczbą.

Porównanie ciągów jest jeszcze trudniejsze. A wszystko dlatego, że po pierwsze stringi są obiektami, a po drugie w zależności od sytuacji programista często chce, aby porównanie stringów przebiegało trochę inaczej (uwzględniając lub nie uwzględniając pewnych czynników).


2. Układ ciągów znaków w pamięci

Jak już widziałeś, ciągi znaków są przechowywane w pamięci inaczej niż liczby całkowite i rzeczywiste:

Lokalizacja ciągów znaków w pamięci

Do przechowywania łańcuchów używane są dwa bloki pamięci : jeden blok przechowuje sam tekst (jego rozmiar zależy od rozmiaru tekstu), a drugi (4 bajty) przechowuje adres pierwszego bloku.

Chociaż doświadczony programista w takiej sytuacji powie coś w stylu „ Zmienna strtypu Stringprzechowuje odniesienie do obiektu typu String”.


3. Przypisywanie referencji do ciągów znaków

Korzyść z tego podejścia staje się oczywista, jeśli trzeba przypisać jedną zmienną łańcuchową do innej zmiennej łańcuchowej. Przykład:

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

A oto, co w rezultacie zostanie w pamięci:

Przypisywanie odwołań do ciągów znaków

W wyniku tej operacji przypisania obiekt Stringpozostanie tam, gdzie był, a message do zmiennej zostanie skopiowany tylko jego adres (odniesienie do obiektu).


4. Praca z linkami i obiektami

Ale jeśli zdecydujesz się zamienić łańcuch na wielkie litery (wielkie litery), maszyna Java zrobi wszystko dobrze: będziesz mieć dwa obiekty typu Stringi zmienne texti messagebędzie przechowywać referencje: każdy do własnego obiektu.

Przykład:

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

A oto, co w rezultacie zostanie w pamięci:

Praca z linkami i obiektami

Zwracam uwagę na fakt, że metoda toUpperCase() nie zmienia linii, na której została wywołana. Zamiast tego tworzy nowy ciąg znaków (nowy obiekt) i zwraca do niego odwołanie.

Albo jeszcze ciekawszy przykład. Powiedzmy, że decydujesz się przekazać ciąg znaków do obiektu typu Scanner(tak, aby odczytywał z niego wartości).

Przykład:

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

Więcej o pracy klasy Scannermożna dowiedzieć się pod linkiem .

Oto jak to wszystko zostanie zapisane w pamięci:

Praca z linkami i obiektami.  Skaner

Jednocześnie Stringprzechowywany jest tam obiekt tego typu, jaki był w pamięci w jednym egzemplarzu - wszędzie przesyłane i przechowywane są tylko odniesienia do niego.


5. Porównywanie odwołań do obiektów typuString

I wreszcie doszliśmy do najciekawszej części - porównań strun.

Do porównania zmiennych łańcuchowych można użyć dwóch operatorów: ==(równa się) i !=(nie równa się). Operatory "większy niż", "mniejszy niż", "większy lub równy" nie mogą być użyte - kompilator na to nie pozwoli.

Istnieje jednak interesujący niuans: co przechowujemy w zmiennych łańcuchowych? Zgadza się: adresy (linki) do obiektów. Te właśnie adresy zostaną porównane i będą to:

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

Oto, co zostanie w pamięci:

Porównanie odwołań do obiektów typu String

Zmienne messagei textprzechowują adres (link) tego samego obiektu. Ale zmienne przechowują s1również s2odniesienia do bardzo podobnych obiektów, ale wciąż nie do tego samego obiektu.

A jeśli porównasz te 4 zmienne w kodzie, otrzymasz następujący wynik:

Kod Wyjście na wyświetlaczu
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