Java. Pytania rekrutacyjne dla Juniora: Co to jest String Pool i porównania Stringów (łańcuchów).

Pytanie to może wydawać się proste, bo już po samej nazwie możemy domyślać się o co chodzi ze String Pool. Jednak na wstępie warto przytoczyć pojęcie mutowalności (zmienności) obiektów, a właściwie to niemutowlności (niezmienności) na przykładzie łańcuchów znaków, czyli Stringów. 

Czym jest String Pool?

Co to znaczy, że String jest niemutowalny? Otóż po utworzeniu nowego obiektu klasy String nie możemy go już zmienić. Wykonując operacje na łańcuchach w tle tworzymy nowe obiekty, a nie modyfikujemy dotychczasowe. Możecie to zobaczyć na przykładzie:

String testA = "test";
String testB = "test";
String testC = new String("test");
String testD = "TEST";
String testE = testA.toUpperCase();

System.out.println("testA " + System.identityHashCode(testA));
System.out.println("testB " + System.identityHashCode(testB));
System.out.println("testC " + System.identityHashCode(testC));
System.out.println("testD " + System.identityHashCode(testD));
System.out.println("testE " + System.identityHashCode(testE));
System.out.println("testA to upper case " + System.identityHashCode(testA.toUpperCase()));

Jak myślicie, co pojawi się w konsoli? Wszystkie Stringi będą unikalnymi obiektami, czyli będą mieć różne wartości hashCode?

 testA 492228202
 testB 492228202
 testC 1368884364
 testD 401625763
 testE 772777427
 testA to upper case 83954662 

Jak widzicie dwa pierwsze Stringi mają ten sam hashCode, a tym samym nie są unikalne i zajmują to samo miejsce w pamięci. I właśnie dotarliśmy do sedna tego wpisu, czyli do String Pool. 

String Pool jest miejscem na stercie (ang. heap), dzięki któremu JVM może optymalizować użycie pamięci. Każdy String jest przechowywany w String Pool, ale gdy wartość Stringa jest jest już dostępna w puli, to zamiast tworzyć nowy obiekt, po prostu tworzona jest referencja do już istniejącego łańcucha. Chyba, że String został stworzony przy użyciu słowa kluczowego new, wówczas i tak tworzony jest nowy obiekt. Stąd inny hashCode dla pola testC.

Spójrz teraz na trzy ostatnie wyniki. Mimo, że ich wartości będą takie same i w każdym przypadku będzie to “TEST”, to każde pole zwraca inny hashCode. Dzieje się tak, ponieważ implementacja metody toUpperCase() zwraca Stringa ze słowem new.

Dlaczego jednak wyszliśmy od niemutowalności łańcuchów? Gdyby Stringi można było modyfikować String Pool nie mógłby zaistnieć. Co gdybyśmy zmieni wartość pola testA, czy wtedy zmieniłaby się wartość pola testB, skoro w obu przechowywana jest ta sama referencja?

Porównania Stringów == czy equals()?

Wiesz już może, jakie są różnice między porównaniem == a metodą equals() w Javie? Pokrótce w przypadku obiektów porównanie == sprawdza czy referencje są takie same. Natomiast metoda equals() sprawdza czy dane obiekty są takie same według określonych założeń, i tak implementacja metody equals() dla Stringa sprawdza czy wszystkie znaki w porównywanych Stringach są takie same.

Jakie więc otrzymamy efekty porównania Stringów testA, testB i testC?

 System.out.println(testA == testB); // true
 System.out.println(testA == testC); // false
 System.out.println(testA.equals(testB)); // true
 System.out.println(testA.equals(testC)); // true 

Istnieje jednak sposób by  za pomocą == uzyskać zgodność dla pól testA i testC. Służy do tego metoda intern() wywoływana na Stringu. Dokonuje ona tzw. internowania, czyli przechowywania obiektu w puli unikatowych wartości. Czyli takiej puli, w której nie ma możliwości utworzenia dwóch łańcuchów o takiej samej treści. Dwa Stringi utworzone przez słowo kluczowe new, dzięki internowaniu będą zwracać tę samą referencję i można je porównać za pomocą ==.

 System.out.println(testA == testC.intern()); // true
 System.out.println(new String("test").intern() == testC.intern()); // true 

Mam nadzieję, że przybliżyłem temat i chociaż może on wydawać się mało istotny, sam spotkałem się kiedyś z pytaniem rekrutacyjnym o internowanie Stringów.

Jeżeli macie uwagi bądź pytania, piszcie w komentarzach.

PS. Staram się używać zamiennie polskich i oryginalnych nazw. W programowaniu angielski jest podstawowym językiem i często w ogóle nie używa się polskich określeń. Czasem polskie nazwy potrafią wręcz wprawić w zakłopotanie, jednak spotykam się z nimi w literaturze czy na innych blogach, więc taka zamienność nazw mam nadzieję, że będzie jedynie pomocna dla osób zaczynających programować.

Java. Pytania rekrutacyjne dla Juniora: Co to jest String Pool i porównania Stringów (łańcuchów).

Jedna myśl na “Java. Pytania rekrutacyjne dla Juniora: Co to jest String Pool i porównania Stringów (łańcuchów).

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Przewiń do góry