Ответ
Неизменяемость (immutability) класса String — это фундаментальный дизайн-выбор, который обеспечивает безопасность, производительность и предсказуемость.
Ключевые причины и преимущества:
-
Безопасность и потокобезопасность:
- Строки часто хранят конфиденциальные данные (пароли, токены). Неизменяемость гарантирует, что они не будут изменены после создания.
- Объекты
Stringможно безопасно использовать в многопоточных средах без синхронизации.
-
Кэширование хэш-кода:
// Поле hash кэшируется при первом вычислении private int hash; // По умолчанию 0 public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { hash = h = calculateHash(value); } return h; }- Хэш-код вычисляется один раз, что критически важно для производительности в
HashMap,HashSet.
- Хэш-код вычисляется один раз, что критически важно для производительности в
-
Пулы строк (String Pool):
String s1 = "Hello"; // Попадает в пул String s2 = "Hello"; // Переиспользует объект из пула System.out.println(s1 == s2); // true (один и тот же объект)- Пул возможен только благодаря неизменяемости, что экономит память и ускоряет сравнение через
==.
- Пул возможен только благодаря неизменяемости, что экономит память и ускоряет сравнение через
-
Безопасная передача в качестве ключа:
Map<String, Integer> cache = new HashMap<>(); String key = "config"; cache.put(key, 42); // Гарантия: ключ не может измениться и не "сломает" хэш-таблицу -
Защита от случайного изменения: Библиотечные методы, получающие
String, могут быть уверены, что исходные данные не изменятся.
Как достигается неизменяемость?
- Класс объявлен как
final(нельзя наследоваться). - Поле
value(массив символов) —private final. - Отсутствуют сеттеры для изменения
value. - Методы, якобы изменяющие строку (например,
substring,concat), возвращают новый объектString.
Следствие: Операции конкатенации в циклах неэффективны — для этого следует использовать StringBuilder.