Пул строк и сравнение строк
Вопрос
Расскажите, как устроен пул строк, когда две строки равны по == и почему сравнивать нужно через equals.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Литералы и константные выражения попадают в пул автоматически
new String создаёт новый объект в куче
Склейка в рантайме даёт новый объект, кроме final-констант
intern возвращает каноничный экземпляр
Пул в куче с Java 7, строки из него собираются GC
== сравнивает ссылки, поэтому только equals
Что могут спросить следом
- Где хранился пул до Java 7 и почему перенесли?
- Стоит ли вызывать intern для экономии памяти?
- Что такое String deduplication в G1?
Разбор
Пул строк это таблица каноничных экземпляров. Все литералы и константные выражения вроде "a" + "b" компилятор и JVM кладут туда, поэтому два одинаковых литерала это один объект и == на них даёт true. new String("x") всегда создаёт новый объект в куче, склейка переменных в рантайме тоже. Исключение: если переменная final и инициализирована литералом, выражение константное и склеивается при компиляции. intern() возвращает экземпляр из пула, добавляя строку, если её не было. С Java 7 пул живёт в обычной куче и чистится сборщиком, раньше был в PermGen и мог переполнить его. Из-за всех этих тонкостей == для строк ненадёжен, сравниваю через equals. Для экономии памяти на дублях в G1 есть флаг -XX:+UseStringDeduplication, он объединяет внутренние массивы, ручной intern нужен редко.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.