String – najważniejszy typ danych

String

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. Klasą reprezentującą ciąg znaków w Javie jest klasa String.

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.

Java – String – wprowadzenie

Z tego materiału dowiesz się:

  • Czym jest String?
  • Czym jest literał?
  • Co oznacza niezmienność String’a?
  • Czym jest pula String’ów?
  • Jak wygląda konkatenacja String’ów?

Java – String vs. string literał (ang. literal)

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:

""                    // pusty string
"\""                  // string zawierający tylko znak "
"Java"                // przykładowy string

"Ala ma " +           // połączenie ze sobą
    "kota"            // dwóch literałów łańcuchowych

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

String str1 = "Java";
String str2 = new String("Java");
String str3 = new String(str2);

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

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 String’a wymuszamy utworzenie nowego obiektu.

Java – String vs. string literał – 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.

Java – Immutable – 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:

String str = "Java";
str += " 8";

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.

Java – Immutable String – Korzyści

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 String’a wiele referencji można wskazywać na jeden obiekt. Pozwala to znacząco zaoszczędzić wykorzystywaną pamięć w aplikacji.

Java – String – Immutable – niezmienne obiekty

W ramach tego materiału zajmujemy się przede wszystkim String’iem i jego właściwościami – natomiast materiał dotyczący zagadnienia niezmienności obiektów (ang. immutable) znajdziesz poniżej.

➡ ZOBACZ 👉: Immutable – niezmienne obiekty

Java – Pula Stringów (ang. string pool) – wewnętrzna optymalizacja JVM

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 (ang. 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 string’a 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 str1 = new String("Java");
String str2 = new String("Java");

String v1 = str1.intern();
String v2 = str2.intern();

assertTrue(str1.equals(str2));
assertFalse(str1 == str2);

assertTrue(v1.equals(v2));
assertTrue(v1 == v2);

Java – String – Konkatenacja

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

String str1 = "Java";
String str2 = " 8";

String expectedValue = "Java 8";

// 1
String actualValue = str1 + str2;

// 2
actualValue = str1.concat(str2);

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

  1. Operator dodawania (konkatenacji) „+”,
  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.

Java – StringBuilder

W ramach tego materiału zajmujemy się przede wszystkim String’iem i jego właściwościami – natomiast materiał dotyczący StringBuildera znajdziesz poniżej.

➡ ZOBACZ 👉: StringBuilder: czy zawsze taki szybki?

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.

// 1
String actualValue = 1 + 2 + "5";
String expectedValue = "35";
assertEquals(expectedValue, actualValue);

// 2
actualValue = "1" + 2 + 5;
expectedValue = "125";
assertEquals(expectedValue, actualValue);

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”.

Java – String – 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. W ramach tego materiału zajmujemy się przede wszystkim String’iem i jego właściwościami – natomiast pełen materiał dotyczący konwertowania typów znajdziesz poniżej.

➡ ZOBACZ 👉: String – konwertowanie i zamiana typów

Java – String – Główne metody

W ramach tego materiału zajmujemy się przede wszystkim String’iem i jego właściwościami – natomiast materiał dotyczący metod klasy String oraz przykłady wykorzystania tych metod znajdziesz poniżej.

➡ ZOBACZ 👉: String – najważniejszy typ danych

➡ ZOBACZ 👉: String – przykłady i testy

Java – String – podsumowanie

W ramach tego materiału dowiedzieliśmy się, czym jest String i jakie działania można na nim wykonać. Bliżej zapoznaliśmy się z zagadnieniem niezmienności oraz puli String’ów. Jeżeli chcesz kontynuować swoją przygodę z Javą i poznać inne struktury, które oferuję ten język programowania – to zapraszam do kolejnego tematu z serii o Javie. Tym razem zagłębimy się w temat operatorów logicznych.

➡ ZOBACZ 👉: Operator logiczne

Kierunek Java

W serii o Javie zapoznajesz się z podstawowymi tematami o Javie. Jeżeli chcesz bardziej kompleksowo zagłębić się w temat Javy, poczytać, posłuchać o Javie, to zachęcam Cię do zapoznania się z moim kursem „Kierunek Java”:

➡ ZOBACZ 👉: Kierunek Java


20+ BONUSOWYCH materiałów z programowania

e-book – „8 rzeczy, które musisz wiedzieć, żeby dostać pracę jako programista”,
e-book – „Java Cheat Sheet”,
checklista – „Pytania rekrutacyjne”
i wiele, wiele wiecej!

Jak zostać programistą

No comments
Share:

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *