Рассмотрим:
String s1 = new StringBuilder("Cattie").append(" & Doggie").toString();
System.out.println(s1.intern() == s1); // true why?
System.out.println(s1 == "Cattie & Doggie"); // true another why?
String s2 = new StringBuilder("ja").append("va").toString();
System.out.println(s2.intern() == s2); // false
String s3 = new String("Cattie & Doggie");
System.out.println(s3.intern() == s3); // false
System.out.println(s3 == "Cattie & Doggie"); // false
Я запутался, почему они получаются по-разному из-за возвращаемого значения из String.intern()
, которое говорит:
Когда метод intern вызывается, если пул уже содержит строку, равную этому объекту String, как определено методом equals (Object), возвращается строка из пула. В противном случае этот объект String добавляется в пул и возвращается ссылка на этот объект String.
Особенно после этих двух испытаний:
assertFalse("new String() should create a new instance", new String("jav") == "jav");
assertFalse("new StringBuilder() should create a new instance",
new StringBuilder("jav").toString() == "jav");
Однажды я прочитал пост, в котором говорится о каком-то special strings
интернированном раньше всего остального, но сейчас это настоящее размытие.
Если есть строки pre-interned
, есть ли способ получить их список? Мне просто интересно, какими они могут быть.
Обновлено
Благодаря помощи @Eran и @Slaw я наконец-то могу объяснить, что только что произошло там для вывода
true
true
false
false
false
- Поскольку
"Cattie & Doggie"
не существует в пуле, s1.intern () поместит текущую ссылку на объект в пул и вернет себя, поэтому s1.intern() == s1
;
"Cattie & Doggie"
уже в пуле, поэтому строковый литерал "Cattie & Doggie"
будет просто использовать ссылку в пуле, которая на самом деле s1
, так что мы снова имеем true
;
new StringBuilder().toString()
создаст новый экземпляр, пока "java"
уже находится в пуле, и тогда ссылка на пул будет возвращена при вызове s2.intern()
, поэтому s2.intern() != s2
и у нас false
;
new String()
также вернет новый экземпляр, но когда мы попытаемся s3.intern()
, он вернет ранее сохраненную ссылку в пуле, которая на самом деле s1
, поэтому s3.intern() != s3
, и у нас будет false
;
- Как уже обсуждалось # 2, строковый литерал
"Cattie & Doggie"
вернет ссылку, уже сохраненную в пуле (которая на самом деле s1
), поэтому s3 != "Cattie & Doggie"
и мы снова получим false
.
Спасибо, что @Sunny предоставил трюк для получения всех interned
строк.