Конкатенация и интернирование строк в Java

Вопрос 1

String a1 = "I Love" + " Java";
String a2 = "I Love " + "Java";
System.out.println( a1 == a2 ); // true

String b1 = "I Love";
b1 += " Java";
String b2 = "I Love ";
b2 += "Java";
System.out.println( b1 == b2 ); // false

Я понимаю, что в первом случае это конкатенация двух строковых литералов, поэтому результат «Я люблю Java» будет интернирован, и результат будет истинным. Однако насчет второго случая я не уверен.

вопрос 2

String a1 = "I Love" + " Java"; // line 1
String a2 = "I Love " + "Java"; // line 2

String b1 = "I Love";
b1 += " Java";
String b2 = "I Love ";
b2 += "Java";
String b3 = b1.intern();
System.out.println( b1 == b3 ); // false

Вышеупомянутое возвращает false, но если я закомментирую строки 1 и 2, он вернет true. Это почему?


person wli75    schedule 18.07.2017    source источник
comment
Мы никогда не сравниваем строки с помощью оператора == и вместо этого используем метод .equals   -  person Joey Pinto    schedule 18.07.2017
comment
@JoeyPinto OP использует ==, чтобы узнать о внутреннем устройстве Java, обнаруживая поведение, которое выглядит довольно странно, но имеет разумное объяснение.   -  person Sergey Kalinichenko    schedule 18.07.2017


Ответы (2)


Первая часть вашего вопроса проста: компилятор Java рассматривает объединение нескольких строковых литералов как один строковый литерал, т.е.

"I Love" + " Java"

а также

"I Love Java"

- это два идентичных строковых литерала, которые правильно интернируются.

То же поведение интернирования не применяется к += операции со строками, поэтому b1 и b2 фактически создаются во время выполнения.

Вторая часть сложнее. Напомним, что b1.intern() может возвращать b1 или какой-либо другой String объект, который ему равен. Если вы оставите a1 и a2, вы получите a1 обратно после звонка на b1.intern(). Когда вы закомментируете a1 и a2, существующая копия не будет возвращена, поэтому b1.intern() вернет вам сам b1.

person Sergey Kalinichenko    schedule 18.07.2017

Из документов intern ()

Все литеральные строки и константные выражения со строковыми значениями интернированы. Строковые литералы определены в разделе 3.10.5 Спецификации языка Java ™.

И из JLS 3.10.5

  • Strings computed by constant expressions (§15.28) are computed at compile time and then treated as if they were literals.
    • Strings computed by concatenation at run time are newly created and therefore distinct.

Ваша строка b1 на самом деле не интернирована. Отсюда разница.

person Suresh Atta    schedule 18.07.2017