Sobes.tech
Middle

Jak łańcuchy są przechowywane w pamięci w języku Java?

sobes.tech AI

Odpowiedź od AI

W Javie, łańcuch (String) jest obiektem niezmiennym. Jego wartość jest reprezentowana przez sekwencję znaków.

Do Java 9, String przechowywał znaki w tablicy char[]. Każdy znak zajmował 2 bajty (UTF-16).

// Do Java 9
public final class String implements Serializable, Comparable<String>, CharSequence {
    private final char value[]; // Znaki łańcucha
    private final int offset;   // Początkowe przesunięcie
    private final int count;    // Liczba znaków (długość)
    // ... inne pola i metody
}

Od Java 9, aby zaoszczędzić pamięć, String może używać tablicy byte[] lub char[]. Kodowanie jest określane przez flagę coder.

// Od Java 9
public final class String implements Serializable, Comparable<String>, CharSequence {
    private final byte[] value; // Znaki łańcucha (byte[] lub char[] w rzeczywistości, w zależności od coder)
    private final byte coder;   // Kodowanie: 0 dla Latin-1, 1 dla UTF-16
    // ... inne pola i metody
}

Literały łańcuchowe (dozwolone znaki) oraz łańcuchy tworzone za pomocą operatora new String(...) są przechowywane na "stercie" (heap).

Literały łańcuchowe są również umieszczane w "puli łańcuchów" (String Pool), która znajduje się w obszarze pamięci PermGen (przed Java 8) lub MetaSpace (od Java 8). Jeśli łańcuch o takiej samej wartości już istnieje w puli, używana jest referencja do istniejącego obiektu.

String s1 = "hello"; // Tworzy "hello" w puli łańcuchów (jeśli jeszcze nie istnieje), s1 odwołuje się do niego
String s2 = "hello"; // s2 odwołuje się do tego samego obiektu "hello" w puli
String s3 = new String("hello"); // Tworzy nowy obiekt "hello" na stercie, s3 odwołuje się do niego. "hello" może być w puli

Ponieważ łańcuchy są niezmiennicze, zmiana wartości łańcucha (np. konkatenacja) prowadzi do utworzenia nowego obiektu String w pamięci.