String Pool
W poprzedniej lekcji na temat porównań wspomniałem, że porównania Stringów też należą do wyjątkowego przypadku. I właśnie o tym sobie powiemy w tej lekcji. 😉
Porównujmy!
Rozpocznijmy od przeanalizowania przykładu, a później do małej refleksji nad nim.
Na początku stwórzmy kilka Stringów, pierwszy przy użyciu cudzysłowów – czyli jak zwykle:
String pablo = "pablo";
Przy użyciu operator new – w końcu String jest obiektem i ma konstruktor:
String drugiPablo = new String("pablo");
No i jeszcze jakiegoś jednego:
String trzeciPablo = "pablo";
No i może jeszcze takiego:
String czwartyPablo = new String("pablo");
Jak zdążyłeś zauważyć wszystkie wartości są takie same – ciekawe czy wszystkie porównania zwrócą prawdę. 😉
Porównajmy sobie Stringi:
if (pablo == trzeciPablo) { System.out.println("Pablo równa się trzeciPablo"); } else { System.out.println("Pablo nie równa się trzeciPablo"); }
I jeszcze w taki sposób:
if (pablo == drugiPablo) { System.out.println("Pablo równa sie drugipablo(1)"); } else { System.out.println("Pablo nie równa się drugiPablo(1)"); }
I jeszcze takie porównanie:
if (pablo.equals(drugiPablo)) { System.out.println("Pablo równa sie drugipablo(2)"); } else { System.out.println("Pablo nie równa sie drugipablo(2)"); }
I już ostatnie:
if (drugiPablo == czwartyPablo) { System.out.println("drugiPablo równa sie czwartyPablo"); } else { System.out.println("drugiPablo nie równa się czwartyPablo"); }
No i mamy cztery porównania – uruchommy program:
Zastanówmy się…
Po uruchomieniu programu otrzymaliśmy coś takiego:
Pablo równa się trzeciPablo Pablo nie równa się drugiPablo(1) Pablo równa sie drugipablo(2) drugiPablo nie równa się czwartyPablo
Przeanalizujmy każdego porównanie.
Pierwsze porównanie pablo == trzeciPablo zwróciło prawdę – dlaczego?
Oba Stringi są niby takie same, ale w końcu to obiekty – a ich adresy są różne, to dlaczego otrzymaliśmy prawdę?
Prawda została zwrócona, ponieważ oba obiekty tak naprawdę są w String Pool – więc mają ten sam adres, ale jak to?
Każdy String utworzony przy użyciu cudzysłowów jest wrzucany do tak zwanego String Poola – jeżeli, więc dwa Stringi mają te samą wartość i zostały utworzony przy użycu cudzysłowów to oznacza, że ich adres jest taki sam. Po przeanalizowaniu wszystkich przykładów wrócę do głębszego omówienia String Poola.
Kolejne porównanie pablo == drugiPablo zwróciło już fałsz – dlaczego?
Jak wiesz obiekt pablo leży już w String Pool – zaś obiekt drugiPablo został utworzony przy użyciu operatora new dlatego nie został wrzucony do String Poola. Wniosek jest taki, że oba obiekty mają inne adresy, więc porównanie == zwraca fałsz.
Następne porównanie to pablo.equals(drugiPablo)), który oczywiście zwraca prawdę – używamy na obiekcie metody equals, która jak wspomniałem w poprzedniej lekcji sprawdza zawartość obiektu, a nie tylko jego adres!
Ostatnie porównanie to: drugiPablo == czwartyPablo – i oczywiście zwróciło fałsz. Dlaczego?
Oba obiekty zostały utworzone przy użyciu operatora new – w takim razie żaden z nich nie jest w String Pool. W takim razie mają one inne adresy – tak jakbyśmy tworzyli zwykłe obiekty.
Omówiliśmy już porównania – zagłębmy się teraz w ten cały String Pool.
Czym jest dokładnie String Pool…
String Pool to taki obszar w pamięci, do którego są wrzucane Stringi utworzone przy użyciu cudzysłowów. No tak tyle już wiesz z akapitu wyżej. No to mówię więcej.
Podczas wrzucania Stringa do String Poola najpierw jest sprawdzane czy w całym String Pool istnieje String o dokładnie takiej wartości. Jeżeli istnieje to zwracany jest adres już tego istniejącego Stringa w String Pool.
Wnioski są proste – w String Pool znajdują się tylko Stringi utworzone przy użyciu cudzysłowów np. String name = “pablo” – i Stringi mieszczące się w nim się nie potwarzają! Jeżeli jakiś nowy String się powtarza to zwracany jest adres już tego istniejącego!
Po co?
String Pool został wprowadzony w celu optymalizacji Javy – znaki mają to do siebie, że zajmują sporo miejsca. Dlatego, aby zmniejszyć ilość zajmowanego miejsca został stworzony String Pool, który nie przechowuje duplikatów – dzięki temu wirtualna maszyna Javy zużywa mniej pamięci. 😉
Podsumowanie
Podsumowując, Stringi najlepiej jest tworzyć przy użyciu cudzysłowiów – wtedy utworzone obiekty będą trafiać do String Pool i nie będą niepotrzebnie zajmowały miejsca.
Każde porównanie Stringa wykonuj przy użyciu metody equals – operator == nie zawsze Ci pomoże!
Aby mieć pewność, że rozumiesz całe zagadnienie odpowiedz w komentarzu na pytanie, które porównanie zwróci true, a które false – każdą odpowiedź uzasadnij dlaczego. 😉
public class Main { public static void main(String[] args) { String john = "john"; String johny = "johny"; String newJohn = new String("john"); String nextJohny = new String("johny"); String nextJohn = new String("john"); String oldJohn = john; String amy = "amy"; String nextAmy = new String("amy"); System.out.println("1." + (john == johny)); System.out.println("2." + (nextJohny == johny)); System.out.println("3." + (john == nextJohn)); System.out.println("4." + newJohn.equals(john)); System.out.println("5." + (oldJohn == john)); System.out.println("6." + (amy == nextAmy)); System.out.println("7." + amy.equals(nextAmy)); } }
Przypominam, że na odpowiedzi czekam w komentarzach. 😉
1. false
2. false
3. false
4. true
5. true
6. false
7. true
Łatwe 🙂
PS. Jak wchodzę przez link: https://1024kb.pl/category/kurs-java-od-podstaw/tydzien-3/ to nie widać wszystkich tematów tylko jeden: “Zabezpieczony: Aplikacja domowa – zadanie”
Wejdź przez link z maila.
Dobra ale nie chcę za każdym razem wchodzić na maila, żeby się dostać do kursu
Niestety dostęp do kursu jest zablokowany hasłem i każda publikacja lekcji pokazywałaby się na stronie głównej, której nie chce zaśmiecać lekcjami. Dlatego widoczność lekcji jest zablokowana z poziomu strony głównej i kategorii.
Aby mieć dostęp do kursu wystarczy dodać do zakładek przeglądarki stronę https://1024kb.pl/kurs-java-od-podstaw/ aby widzieć zbiór wszystkich lekcji. 😉
1. fałsz
2. fałsz
3. fałsz
4. prawda
5. prawda
6. fałsz
7. prawda
1. false – mają różną wartość, zatem nie są duplikatami, nie trafiają do String pool więc mają inne adresy w pamięci
2. false – nextJohny jest twórzony jako nowy obiekt, więc ma swój adres, inny niź johny
3. false – to samo co powyżej
4. true – porównywana jest wartość Stringów, więc są równe
5. true – do oldJohn został przypisany jest adres john, więc są równe
6. false – to samo co w przykładzie drugim
7. true – to samo co w przykładzie czwartym