Рассматривать:
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
строки.