Ответ
Выделение памяти для строки в Java зависит от способа её создания и связано с двумя областями памяти: куча (heap) и пул строк (String Pool).
1. Создание строки-литерала:
String s1 = "Hello";
- Строка
"Hello"ищется в String Pool (специальная область heap для уникальных литералов). - Если найдена —
s1получает ссылку на существующий объект. - Если не найдена — объект создаётся в пуле, и ссылка сохраняется там.
- Цель: экономия памяти за счёт повторного использования неизменяемых строк.
2. Явное создание через new:
String s2 = new String("Hello");
- Всегда создаёт новый объект в куче (heap), даже если идентичная строка есть в пуле.
- Ссылка на литерал
"Hello"из пула используется для инициализации, ноs2указывает на отдельный объект.
3. Операции, изменяющие строку (конкатенация, substring в старых версиях):
String s3 = s1 + " World"; // "Hello World"
- Так как строки неизменяемы (immutable), любая операция, модифицирующая содержимое, создаёт новый объект String в куче.
- Компилятор может оптимизировать конкатенацию литералов, но в общем случае это дорогая операция.
Практические следствия и best practices:
- Для многократного изменения строки используйте
StringBuilder(не потокобезопасный) илиStringBuffer(потокобезопасный). - Сравнение строк:
s1.equals(s2)для сравнения содержимого,s1 == s2— для проверки, ссылаются ли переменные на один и тот же объект в памяти. - Метод
String.intern()позволяет вручную поместить строку в пул и получить на неё ссылку.