Получить доступ

Почему String в Java неизменяемый?

MiddleОсновы языка
Коротко

Неизменяемость String даёт пул строк (литералы разделяются безопасно), кэш hashCode (строка — идеальный ключ HashMap), потокобезопасность без синхронизации и безопасность: проверенный путь к файлу или имя класса нельзя подменить после проверки.

  • Любая «модификация» создаёт новый объект
  • Конкатенация в цикле — StringBuilder
  • Пароли хранят в char[], чтобы можно было затереть

А ещё Внутри — массив байт (компактные строки Java 9: Latin-1 или UTF-16)

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Почему это важно для языка:

  • Пул строк. Литерал "abc" в разных местах программы — один объект. Это возможно только потому, что никто не может его изменить.
  • Хеш-код вычисляется один раз и кэшируется в поле — повторные hashCode() бесплатны. Ключ HashMap не может «уехать» после вставки.
  • Потокобезопасность. Строку можно передавать между потоками без синхронизации.
  • Безопасность. checkPermission(path); open(path) — если бы строку можно было поменять между вызовами, проверка была бы бессмысленной. То же для имён классов в загрузчиках, URL, параметров сети.

Как устроено: класс final, поле с данными private final byte[], ни один метод не меняет массив. substring, replace, toUpperCase возвращают новые строки.

Цена — новые объекты при каждой «правке». Конкатенация в цикле квадратична, поэтому StringBuilder. Компилятор сам превращает a + b + c в одно выражение (Java 9+: invokedynamic StringConcatFactory), но внутри цикла так не сделает.

Пароли хранят в char[]: строку нельзя затереть, и она может долго висеть в памяти и попасть в дамп.

Что хотят услышать

  • Пул, кэш хеша, потокобезопасность, безопасность.
  • Цена неизменяемости и StringBuilder.

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

  • Думать, что методы String меняют строку на месте.
  • Конкатенировать строки через + в цикле.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Чтобы строки можно было менять из разных потоков
  • ✗Это ограничение JVM без причины
  • ✗Чтобы экономить память изменением на месте
  • ✓Ради безопасности, кэширования hashCode, потокобезопасности и шаринга через пул

Что спросят дальше

  • Что делает intern()?
  • Чем StringBuilder отличается от StringBuffer?

Разбор темы

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем