Что делает метод intern() у строк (String) в Java?

Ответ

Метод String.intern() помещает строку в пул строк (String Pool), если её там ещё нет, и возвращает каноническое представление — ссылку на строку из пула. Это позволяет оптимизировать память, гарантируя, что литерально одинаковые строки будут представлены одним объектом.

Как это работает:

String s1 = new String("hello"); // Создаётся в heap, вне пула
String s2 = s1.intern();         // Помещает "hello" в пул (или находит) и возвращает ссылку из пула
String s3 = "hello";            // Литерал — берётся из пула

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

Без intern():

String s1 = new String("hello"); // Объект в heap
String s2 = "hello";            // Объект в String Pool
System.out.println(s1 == s2);   // false: разные объекты в памяти

Важно:

  • С Java 7 пул строк расположен в Heap, а не в PermGen.
  • Неконтролируемое использование intern() может привести к увеличению потребления памяти, так как строки из пула не удаляются сборщиком мусора, пока жив класс, их загрузивший.
  • Используйте осторожно, в основном для долгоживущих строк с высокой вероятностью дублирования.

Ответ 18+ 🔞

Э, слушай, давай про эту вашу String.intern() разжую, а то некоторые до сих пор думают, что это магия какая-то, а не просто хитрая оптимизация памяти, блядь.

Вот представь: у тебя в программе дохуища одинаковых строк плодятся, как тараканы. Каждая — новый объект в памяти, жрёт место. А пул строк — это такой общаг для строк-литералов, куда можно и свои самопальные строки прописать, если очень хочется.

Как эта штука работает, на пальцах:

String s1 = new String("hello"); // Создали строку в куче (heap), как честный, блядь, объект. В пуле её нет.
String s2 = s1.intern();         // Говорим: "А ну-ка, 'hello', иди в общаг, будь как все!" Или находит уже лежащую там. Возвращает ссылку из пула.
String s3 = "hello";            // Берём классический литерал — он автоматом из пула.

System.out.println(s2 == s3); // true! Обе ссылки тычут в один и тот же объект в пуле. Красота, ёпта.

А вот как бывает без этого intern(), когда всё идёт по пизде:

String s1 = new String("hello"); // Объект в куче, гордый и независимый.
String s2 = "hello";            // Литерал — сидит себе в пуле.
System.out.println(s1 == s2);   // false, блядь! Это два разных объекта в памяти. Сравнение по ссылке не прокатит.

А теперь важные детали, на которых все обжигаются:

  • С Java 7 этот ваш пул строк болтается в обычной куче (Heap), а не в том самом PermGen, где ему было тесно. Так что теперь он хоть под сборку мусора попадает, но с оговорками.
  • И вот главная оговорка: используй intern() с мозгом, а не как попало! Заложишь туда миллион уникальных строк — и они там навсегда, как в мавзолее, пока класс живёт. Память сожрёт овердохуища, а потом будешь чесать репу.
  • Юзать это дело стоит только для долгоживущих строк, которые дохуя раз повторяются. Типа ключей в каком-нибудь конфиге. Тогда экономия памяти будет — просто пиздец.

Вот и вся философия. Не делай из молотка микроскоп, и всё будет заебись.