Учитывать:
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()
, в котором говорится:
Если при вызове внутреннего метода пул уже содержит строку, равную этому объекту 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
.