Что такое String Pool

Ответ

String Pool (пул строк) — это специальная область в heap памяти Java, где хранятся уникальные строковые литералы. При создании строки через двойные кавычки ("text") JVM сначала проверяет String Pool на наличие такой же строки. Если находит — возвращает ссылку на существующий объект, иначе создает новый.

Особенности:

  • Экономит память, избегая дублирования.
  • Работает благодаря иммутабельности строк.
  • String.intern() явно добавляет строку в пул (или возвращает существующую).

Пример:

String s1 = "hello"; // Создаётся в String Pool
String s2 = "hello"; // Использует существующую из пула
String s3 = new String("hello"); // Создаёт новый объект в heap

System.out.println(s1 == s2); // true (один объект)
System.out.println(s1 == s3); // false (разные объекты)
System.out.println(s1 == s3.intern()); // true (s3 добавлен в пул)

Ответ 18+ 🔞

А, ну это же классика, ебать мои старые костыли! Сидишь такой, пишешь на Java, и думаешь — ну что может быть проще строки? String s = "привет"; И всё, живи спокойно. А потом бац — у тебя в приложении память жрёт как не в себя, и ты начинаешь копать, а там, ёпта, этот самый String Pool, который всех и спасает, и путает одновременно.

Представь себе такую картину. У тебя есть куча (heap), как склад, куда скидывают все коробки-объекты. А String Pool — это типа отдельная, очень аккуратная полочка на этом складе, где хранятся только уникальные бумажки с надписями. Ты пишешь String s1 = "hello"; — JVM такая: "Так, стоп, 'hello'... Хм, на полочке такого ещё нету. Ладно, печатаем новую бумажку и кладём на полку". Всё, s1 теперь тычет пальцем на эту бумажку.

Потом ты пишешь String s2 = "hello";. JVM опять вникает: "Снова 'hello'? Так, секунду... Опа, а на полочке уже лежит! Ну нахуй новую печатать, вот тебе ссылка на ту же самую бумажку". И s2 начинает показывать на то же самое место. Поэтому s1 == s2 даёт true. Одна и та же бумажка, один объект в памяти. Экономия, красота, доверия ебать ноль, но работает.

А теперь начинается пиздец, чувак. Ты делаешь String s3 = new String("hello");. И тут JVM, блядь, ведёт себя как хитрая жопа. Она сначала, как положено, проверяет полочку (String Pool). Литерал "hello" там есть? Есть. Ну ок, он используется как шаблон. Но оператор new — это священная команда "создай новый объект, ёбаный насос!". И JVM создаёт в общей куче (вне полочки!) совершенно новый, отдельный объект String, с таким же содержимым. Теперь s3 тычет пальцем уже на ЭТУ новую коробку в общем складе. И когда ты сравниваешь s1 == s3, получаешь false. Потому что это РАЗНЫЕ объекты, Карл! Один на аккуратной полочке, другой валяется в общей куче.

И вот тут на сцену выходит наш спаситель — метод intern(). Это такой крик души: "Блядь, я не хочу плодить сущности! Засунь меня на ту самую аккуратную полочку!". Когда ты вызываешь s3.intern(), JVM идёт на полочку, ищет строку с таким же текстом. Находит нашу старую бумажку "hello" и говорит: "Всё, забудь про свою коробку в куче. Вот тебе ссылка на эталон с полки". И после этого s1 == s3.intern() становится true. Потому что intern() вернул ссылку именно на объект из пула.

Итоги, чтобы не ебал мозг:

  • Литералы ("...") — автоматом лезут в пул (или берутся оттуда). Экономия памяти — овердохуища.
  • new String(...) — всегда создаёт новый объект в куче, даже если такой же текст уже есть в пуле. Это как специально наступать на грабли.
  • .intern() — это явный пинок под жопу строке: "Иди-ка ты, дружок, в пул, и больше не отсвечивай новыми объектами".

Короче, если хочешь жить спокойно и не тратить память впустую — работай с литералами или юзай intern(). А new String из литерала — это почти всегда мартышлюшка, если только тебе реально не нужна отдельная, изолированная копия объекта. Вот такая, блядь, магия.