Почему строку (String) в Java считают тяжеловесным объектом?

«Почему строку (String) в Java считают тяжеловесным объектом?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, объект String в Java считается относительно тяжеловесным по нескольким причинам:

  1. Неизменяемость (Immutability): Любая операция, модифицирующая строку (например, конкатенация, substring до Java 7u6), создает новый объект в куче. Это может быстро привести к накоплению мусора и нагрузке на GC.
  2. Внутреннее представление: Строка хранит данные в массиве char[], где каждый символ занимает 2 байта (UTF-16). Для строки "Hello" это 10 байт только на данные, плюс накладные расходы самого объекта и массива.
  3. Накладные расходы объекта: Каждый объект String включает служебные поля (например, hash, value), заголовок объекта и ссылку на массив символов.

Пример и сравнение:

String result = "";
for (int i = 0; i < 1000; i++) {
    result += "a"; // Создается 1000+ новых объектов String!
}
// Лучше использовать StringBuilder для таких операций:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.append("a");
}
String efficientResult = sb.toString(); // Создан всего один новый String

Вывод: Для интенсивных манипуляций со строками предпочтительны StringBuilder (непотокобезопасный) или StringBuffer (потокобезопасный).