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);
}
Results:
true
false
First one prints true
, and the second prints false
. Why are the results different?
The difference in behavior is unrelated to the differences between StringBuilder
and StringBuffer
.
The javadoc of String#intern()
states that it returns
When the intern method is invoked, if the pool already contains a string equal to this
String
object as determined by theequals(Object)
method, then the string from the pool is returned . Otherwise, thisString
object is added to the pool and a reference to thisString
object is returned.
The String
created from
String str2 = new StringBuffer("ja").append("va").toString();
is a brand new String
that does not belong to the pool.
For
str2.intern() == str2
to return false
, the intern()
call must have returned a different reference value, ie. the String
"java"
was already in the pool .
In the first comparison, the String
"计算机软件" was not in the string pool prior to the call to intern()
. intern()
therefore returned the same reference as the one stored in str2
. The reference equality str2 == str2
therefore returns true
.
Because your assignments don't re-read from the intern pool and Java String
(s) are immutable. Consider
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);
The output is (as you might expect)
true
true
Lots of answer before mentioned about the pool and explained really clearly with the Oracle link docs.
I just would like to point out the way we can check when debugging code.
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
You can use any IDE and debug to check the actual address that the str1 and str1.intern()/str2 and str2.intern().
let me add something more interesting:
so I think the right answer is :
diffrent vendor's jvm or jvm versions may have diffrent implemention(the language specification don't force the how to)
In Oracle JDK 8(I guess u using): String “java” already in pool(loaded by java.lang.Version#laucher_name) and String pool only stores the refrence,not the object.
But in OpenJDK the laucher_name is "openJDK";In Oracle JDK 6 and below ,the string pool will copy the string object to itslef .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.