Ответ
Неизменяемость строк в Java означает, что объекты класса String не могут быть изменены после их создания. Любая операция, которая кажется модификацией строки (конкатенация, замена символов, обрезка), на самом деле возвращает новый объект String, оставляя исходную строку нетронутой.
Почему строки сделали неизменяемыми?
- Безопасность в многопоточности: Не требуется синхронизация, так как данные не могут измениться.
- Кэширование и пул строк: JVM хранит литералы и интернированные строки в пуле (
String Pool), что экономит память. - Безопасность: Критические данные (например, пароли в
char[]) не могут быть изменены извне. - Хэш-код: Поскольку строка не меняется, ее
hashCode()можно вычислить один раз и кэшировать, что полезно для ключей вHashMap.
Демонстрация на примере:
String original = "Hello";
String modified = original.concat(" World"); // Создается НОВАЯ строка
System.out.println(original); // Вывод: "Hello" (исходная строка не изменилась)
System.out.println(modified); // Вывод: "Hello World"
// Сравнение ссылок
System.out.println(original == modified); // false - это разные объекты в памяти
Практическое следствие:
// Неэффективно в цикле (создается много временных объектов)
String result = "";
for (int i = 0; i < 100; i++) {
result += i; // Каждая итерация создает новый StringBuilder и String
}
// Эффективно: используйте mutable-класс StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
sb.append(i);
}
String efficientResult = sb.toString();
Классы для изменяемых последовательностей символов:
StringBuilder(не потокобезопасный, высокая производительность).StringBuffer(потокобезопасный, но медленнее из-за синхронизации).
Ответ 18+ 🔞
Да ты посмотри, что эти умники в Java придумали! Строки, блядь, неизменяемые, как скала. Ну то есть создал ты там String s = "Привет" — и всё, пиши пропало. Хочешь добавить "мир" — хуй тебе, а не добавка. Создаётся новая строка, а старая так и остаётся в памяти, как памятник твоей наивности.
А почему, спрашивается, такая дичь? Ну, во-первых, безопасность, ёпта. Представь, у тебя пароль в строке летит между потоками. А тут какой-нибудь поток-хуеплёт возьмёт и изменит её посередке. Пиздец безопасности, да? А так — создали, и хоть потоп, она как была, так и есть. Во-вторых, пул строк. JVM, хитрая жопа, складывает все одинаковые строковые литералы в одну кучу (пул), чтобы память не жрать почём зря. И если бы их можно было менять, то, изменив одну "привет", ты бы, блядь, все "приветы" в программе поменял. Ёперный театр!
И хэш-код, сука! Его можно один раз посчитать и закешировать. Для HashMap это просто песня, а не фича.
Смотри, как это выглядит на практике:
String original = "Hello";
String modified = original.concat(" World"); // Создается НОВАЯ строка
System.out.println(original); // Вывод: "Hello" (исходная строка не изменилась)
System.out.println(modified); // Вывод: "Hello World"
// Сравнение ссылок
System.out.println(original == modified); // false - это разные объекты в памяти
Видал? original остался девственником, а modified — это уже совсем другой объект, новый. Сравниваешь ссылки — false, потому что это два разных куска памяти.
А теперь главный пиздец, куда все новички влипают. Циклы!
// Неэффективно в цикле (создается много временных объектов)
String result = "";
for (int i = 0; i < 100; i++) {
result += i; // Каждая итерация создает новый StringBuilder и String
}
Вот это, блядь, просто убийство производительности! Каждый плюсик — это под капотом создание нового StringBuilder, сборка строки и создание новой String. Мусора — овердохуища! Так делать — себя не уважать.
Как делать правильно? Да вот так, умно:
// Эффективно: используйте mutable-класс StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
sb.append(i);
}
String efficientResult = sb.toString();
Вот StringBuilder — это да, мутабельный чувак, его можно пихать и менять как угодно, и только в конце сделать из него строку. Быстро, эффективно, мать его.
А есть ещё StringBuffer — такой же, но потоко-безопасный, с синхронизацией. Медленнее, конечно, но если твои потоки совсем охренели и одновременно лезут в одну строку — то он.
Короче, запомни: String — для констант, для того, что не меняется. Всё, что нужно активно клепать и менять — StringBuilder (или StringBuffer). И будет тебе счастье, а не утечки памяти и тормоза.