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.