Почему результаты str == str.intern() для этих строк различны?

public static void main(String[] args) {
    String str1 = new StringBuilder("计算机").append("软件").toString();
    System.out.println(str1.intern() == str1);
    String str2 = new StringBuffer("ja").append("va").toString();
    System.out.println(str2.intern() == str2);
}

Результаты:

 true
 false   

Сначала печатается true, а вторая - false. Почему результаты отличаются?

Ответы

Ответ 1

Разница в поведении не связана с различиями между StringBuilder и StringBuffer.

В javadoc String#intern() указано, что он возвращает

Когда вызывается метод intern, , если пул уже содержит строка, равная этому объекту String, как определено equals(Object)метод, то возвращается строка из пула. В противном случае это Объект String добавляется в пул и ссылка на этот Stringобъект возвращается.

String создан из

String str2 = new StringBuffer("ja").append("va").toString();

- это новый String, который не принадлежит пулу.

Для

str2.intern() == str2

для возврата false, вызов intern() должен возвращать другое ссылочное значение, т.е. String "java" уже находился в пуле.

В первом сравнении String "计算机 软件" не был в пуле строк до для вызова intern(). intern() поэтому возвратил ту же ссылку, что и та, которая хранится в str2. Поэтому ссылочное равенство str2 == str2 возвращает true.

Ответ 2

Поскольку ваши назначения не перечитываются из основного пула и Java String (s), неизменяемы. Рассмотрим

String str1 = new StringBuilder("计算机").append("软件").toString();
String str1a = new String(str1); // <-- refers to a different String 
str1 = str1.intern();
str1a = str1a.intern();
System.out.println(str1a == str1);
String str2 = new StringBuffer("ja").append("va").toString();
String str2a = new String(str2); // <-- refers to a different String 
str2 = str2.intern();
str2a = str2a.intern();
System.out.println(str2a == str2);

Выход (как и следовало ожидать)

true
true

Ответ 3

Достаточно много ответов, прежде чем упомянуть о пуле, и четко объяснил это с документами Oracle link.

Я просто хотел бы указать, как мы можем проверить при отладке кода.

    String str1 = new StringBuilder("计算机").append("软件").toString();
    System.out.println(str1.intern() == str1);//the str1.intern() returns the same memory address the str1
    String str2 = new StringBuffer("ja").append("va").toString();
    System.out.println(str2.intern() == str2);//the str2.intern() does not return the same memory address the str2

Вы можете использовать любую IDE и debug для проверки фактического адреса str1 и str1.intern()/str2 и str2.intern().