Короткий ответ
String Pool (пул строк) — специальная область памяти в куче, где JVM хранит строковые литералы, чтобы одинаковые строки не дублировались. Когда код встречает литерал "java", JVM проверяет пул: если такая строка уже есть, переменная получает ссылку на существующий объект, если нет — строка создаётся и помещается в пул. Поэтому сравнение == двух одинаковых литералов даёт true.
Как это работает подробнее
Создание через new String("java") работает иначе: конструктор всегда создаёт новый объект в обычной части кучи, даже если такая строка уже есть в пуле, поэтому new String("java") == "java" даёт false. Переместить строку в пул можно вручную методом intern(), который возвращает канонический объект из пула. До Java 7 пул находился в PermGen, с Java 7 его перенесли в обычную кучу — теперь сборщик мусора может удалять неиспользуемые интернированные строки.
- Интернирование литералов — одинаковые литералы по всей программе разделяют один объект и экономят память.
- new String(...) — всегда отдельный объект в куче, мимо пула, даже при существующем литерале.
- intern() — ручное помещение строки в пул с возвратом канонического объекта.
- Расположение — до Java 7 PermGen, с Java 7 обычная куча.
Пример кода
public class StringPoolDemo {
public static void main(String[] args) {
String s1 = "java"; // создаётся или находится в пуле
String s2 = "java"; // берётся та же ссылка из пула
String s3 = new String("java"); // новый объект в куче, мимо пула
System.out.println(s1 == s2); // true — один объект из пула
System.out.println(s1 == s3); // false — разные объекты
System.out.println(s1 == s3.intern()); // true — канонический объект
}
}