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:

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:
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:

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:

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:

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 |
|---|---|
|
|
GO TO FULL VERSION