Выполняется ли интернирование строк во время компиляции в Java?
Я действительно смущен тем, как string interning работает на Java. Когда я пишу:
String a = "ABC";
String b = "ABC";
if (a==b)
System.out.println("Equal");
Сохраняет ли компилятор строковый литерал "ABC" в пул строковых констант во время компиляции?
Это звучит нелогично, потому что я думал, что строковый постоянный пул был создан JVM во время выполнения, и я не вижу, как это возможно, если это делается во время компиляции, поскольку компилятор Java даже не вызывает JVM.
Если это не сделано во время компиляции, и это выполняется во время выполнения, то почему следующее возвращается false (взято из этого ответа)?
// But .substring() is invoked at runtime, generating distinct objects
"test" == "!test".substring(1) // --> false
Если это выполняется во время выполнения, то почему JVM не может определить, что они являются одной и той же строкой?
Я действительно смущен тем, как работает интерпретация строк в Java и где хранится именно пул строк Java.
Ответы
Ответ 1
Компилятор помещает литеральные строки в файл класса (и только уникальные, он объединяет все эквивалентные литералы); JVM загружает эти строки в пул строк при загрузке файла класса.
Если это выполняется во время выполнения, то почему JVM не может определить, что они являются одной и той же строкой.
Поскольку строка, возвращаемая .substring
, не была интернирована, и это другой объект, чем эквивалентная строка "test"
в пуле строк. Если вы интернировали его, вы получите true
:
"test" == "!test".substring(1).intern() // true
Разделы §4.4 JLS и §5.3 спецификации JVM выглядят релевантными.
Просто чтобы быть ясным: правильный способ сравнения строк в Java - использовать метод .equals
или аналогичный, а не ==
. Использование ==
со строковыми экземплярами обычно неверно. (Если вы не играете с пониманием, когда и как вещи интернированы...)
Ответ 2
Я проверил .class для
String a = "ABC";
String b = "ABC";
и нашел в нем только одну "ABC". Это javac создает одну константу той же строки во время компиляции.
Но если 2 или более классы имеют одну и ту же константу "ABC", то JVM поместит их в одно и то же место в пуле строк