← Назад к списку
ТехническаяJava и KotlinJunior

Почему String в Java неизменяемый и что такое пул строк?

Короткий ответ

  • Объект String нельзя изменить после создания — все методы возвращают новую строку
  • Неизменяемость даёт безопасность, потокобезопасность и кэширование hashCode
  • Литералы складываются в пул строк и переиспользуются
  • new String("a") создаёт отдельный объект вне пула
  • Сравнивать строки нужно через equals, а не ==
  • Для частых конкатенаций в цикле — StringBuilder

String неизменяем ради безопасности, кэширования и пула строк; сравнение — только через equals.

Как сказать вслух

пример ответа

Строка в Java неизменяема: любой метод вроде replace или concat возвращает новый объект, а исходный не трогается. Это даёт три выгоды: строки можно безопасно шарить между потоками, их hashCode кэшируется, и одинаковые литералы переиспользуются через пул строк. Поэтому сравнивать строки надо через equals — оператор сравнения проверяет только, один ли это объект.

Подробный ответ

Основной ответ

String — финальный класс с финальным внутренним массивом (с Java 9 это byte[] благодаря compact strings); ни один метод не меняет содержимое, а возвращает новый объект. Неизменяемость даёт: безопасное использование как ключей HashMap (hashCode вычисляется один раз и кэшируется), потокобезопасность без синхронизации, защиту в API (путь, имя класса не подменят после проверки). Пул строк — таблица в куче, куда попадают все литералы: два одинаковых литерала ссылаются на один объект, поэтому == для них случайно «работает». new String() создаёт копию вне пула, intern() возвращает экземпляр из пула. Конкатенация в цикле порождает мусорные объекты — для этого есть StringBuilder.

Ключевые моменты

  • Зачем неизменяемость. Кэш hashCode, потокобезопасность, безопасность API и возможность пула.
  • Пул строк. Литералы дедуплицируются; intern() добавляет/находит строку в пуле вручную.
  • equals vs ==. == сравнивает ссылки; содержимое — только equals/equalsIgnoreCase.
  • StringBuilder. Изменяемый буфер для сборки строк в циклах; компилятор сам оптимизирует только простые выражения.

Практический контекст

Классический вопрос первого раунда. На практике тема всплывает в багах сравнения через == (особенно после десериализации или new String) и в перформансе — конкатенация в цикле на горячем пути. Интервьюер смотрит, можете ли вы объяснить «почему» неизменяемости, а не только факт, и знаете ли разницу литерала и new String.

Частые ошибки

  • Сравнивают строки через == и уверены, что это всегда работает из-за пула
  • Называют String изменяемым, путая со StringBuilder
  • Говорят, что пул строк находится в PermGen — с Java 7 он в куче

ИП Кочкин Алексей Сергеевич · ИНН 390509026279 · ОГРНИП 325390000030973 · jiniys2005@yandex.ru