Почему результаты 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().