String – najważniejszy typ danych

String

W Javie, jak w większości innych języków programowania, bardzo często mamy do czynienia z różnego rodzaju ciągami znaków. W tekście postaram się przybliżyć Ci takie pojęcia jak literał łańcuchowy i klasa String oraz omówię podstawowe mechanizmy z nimi związane.

Co to jest String i string literał?

Między tymi dwoma pojęciami w praktyce jest niewielka różnica, dlatego zazwyczaj są zamiennie nazywane i wykorzystywane.

Literał łańcuchowy, czyli po prostu ciąg znaków, musi kończyć się i zaczynać od znaku cudzysłowu. Poniżej kilka przykładowych literałów:

Każdy literał łańcuchowy jest jednocześnie Stringiem, a chcąc utworzyć obiekt typu String, do jego konstruktora trzeba podać literał lub inny obiekt String.

Jak widzimy, powyższe mechanizmy są ze sobą bardzo powiązane i podobne. Większość obecnych IDE podpowie, że skorzystaliśmy nadmiarowo z konstruktora Stringa.

String konstruktor

String konstruktor

Główna różnica między nimi polega na tym, że w przypadku literałów łańcuchowych pozwalamy Javie zarządzać tworzonymi obiektami, natomiast korzystając z konstruktora Stringa wymuszamy utworzenie nowego obiektu.

Co jest lepsze?

Właściwa odpowiedz to, jak zawsze: “To zależy”. Jednak w praktyce bardzo rzadko chcemy ręcznie tworzyć obiekty typu String i raczej powinniśmy unikać tego rozwiązania na korzyść literałów.

Immutability, czyli niezmienność Stringów

Raz utworzony obiekt typu string nigdy nie zmieni już swojej wartości. Co to tak naprawdę dla nas znaczy? Takie zachowanie  klasy można porównać do swego rodzaju odlewu w formie. Jeżeli potrzebujemy innego odlewu, trzeba przygotować nową formę.

Zobaczmy to na przykładzie:

Klasa String nie posiada żadnego settera, którym moglibyśmy zmienić jego wartość, dlatego chcąc zmienić tę wartość, tworzymy nowy obiekt oraz modyfikujemy referencje przechowującą odwołanie do tego stringa.

W powyższym przykładzie utworzyliśmy nowy obiekt string o wartości “Java 8” i ustawiliśmy na niego zmienną referencyjną str.

Co nam daje niezmienność Stringów?

  • bezpieczeństwo
    Stringi są wykorzystywane we wszystkich korowych funkcjonalnościach. Dzięki temu, że mamy pewność, że wartość obiektu nie zostanie zmodyfikowana, łatwiej jest zabezpieczyć się przed modyfikacją kodu z zewnątrz.
  • wydajność
    Stringi powszechnie wykorzystywane są jako klucze w mapach. Ponieważ ich wartość nie ulega zmianie, wartość hashCode jest wyliczana tylko jeden raz, co znacząco wpływa na czas wykonania operacji hashMap i hashTable.
  • pulę stringów
    Dzięki niezmienności Stringa wiele referencji można wskazywać na jeden obiekt. Pozwala to znacząco zaoszczędzić wykorzystywaną pamięć w aplikacji.

Pula Stringów – wewnętrzna optymalizacja JVM | String pool

Pula stringów to wewnętrzny mechanizm optymalizacyjny Javy, polegający na przechowywaniu tylko jednej kopii unikatowej wartości stringów.

Taki mechanizm pozwala znacząco zredukować ilość pamięci potrzebnej na przechowanie wszystkich literałów tekstowych.

Pyłek (FlyWeight Pattern)

Wewnętrzna pula stringów została zaimplementowana z wykorzystaniem strukturalnego wzorca projektowego pyłek. Polega on na budowaniu większych obiektów z wielu mniejszych elementów, które mogą być współdzielone między różnymi obiektami.

String intern

Klasa string posiada metodę intern, dzięki której można wymusić pobranie stringa z puli.

public native String intern();

W efekcie czego, jeżeli na obiekcie klasy String utworzonym ręcznie wywołamy tę metodę, Java zwróci obiekt zarządzany przez pulę.

String konkatenacja

Konkatenacja stringów to po prostu łączenie ich ze sobą.

W Javie stringi możemy łączyć na dwa sposoby. Wykorzystując do tego:

  1. Operator dodawania (konkatenacji) + oraz
  2. Metodę concat.

W przypadku łączenia ze sobą większej ilości stringów należy zwrócić uwagę na wydajność rozwiązania. Więcej o tym problemie pisałem przy okazji artykułu o StringBuilder.

Kolejność łączenia stringów  z liczbami

Ponieważ działania wykonywane są w kolejności od lewej do prawej, podobny na pierwszy rzut oka kod może dawać różne rezultaty.

Wpływ ma na to typ dodawanych zmiennych.

  1. Na pierwszym przykładzie najpierw zostały zsumowane liczby do 3 i dopiero potem typ int został zamieniony na string i połączony z “5”.
  2. Natomiast w drugim przykładzie najpierw string “1” został dodany do liczby 2, co wymagało już zamiany int na string. Dlatego finalny wynik to string “125”.

Konwertowanie typów

Ponieważ ciągi znaków występują w połączeniu z praktycznie każdym innym typem. Bardzo często zachodzi potrzeba zamiany jednego typu na inny. Poniżej zestawienie najczęściej występujących konwersji.

Główne metody klasy String

 

Programista – Pytania rekrutacyjne

Lista pytań rekrutacyjnych, które pozwolą przygotować Ci się na rozmowę kwalifikacyjną.

No comments
Share:

Dodaj komentarz

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