Reputation: 177
Before we move on: I understand we should use .equals() to compare content. I am now just talking about if the actual references are the same for the following scenario...
Say we have the following:
String str1 = "str";
String str2 = "string";
String str3 = "ing";
String str4 = str1 + str3;
str1 = str4;
String str5 = "string";
System.out.println(str1==str2);//false
I think it supposed to be true since in the String pool, the reference to "string" should be the same, as str1 and str2, now are both "string". It should be true, but ends up as false.
System.out.println(str1.intern()==str2.intern());//true
I tried this, and it returned a true this time. Then I tried:
System.out.println(str1==str5);//false
System.out.println(str2==str5);//true
Also System.out.println("str"+"ing"=="string");//true
Aren't the supposed to come from the String pool? Could someone help explain this a bit?
Upvotes: 2
Views: 167
Reputation: 896
The comparison works as follows:
String str1 = "str";` //"str" is created in SCP and str1 is a reference to that
String str2 = "string";` //"string" is created in SCP and str2 is a reference
String str3 = "ing";` //"ing" is created in SCP and str3 is a reference
String str4 = str1 + str3;//"string" will be created on Heap and str4 is a reference (this is because if any string created at runntime will always be created on Heap) (here SCP already has this "string" so no change) make a note that str4 is pointing to Heap string Object and not SCP
str1 = str4; `// str1 and str4 will start pointing to same String Object on Heap
String str5 = "string";` // SCP already has this and str2 pointing to that so now onwards str5 will also point to it
based on above
1. str1 and str4 -- > are pointing to "string" object on heap
2. str2 and str5 -- > are pointing to "string" object in scp
3. str3 -- > is pointing to "ing" in scp
and finally the corresponding output can be traced based on above lines:
System.out.println(str1==str2);`//false
System.out.println(str1.intern()==str2.intern());`//true
System.out.println(str1==str5);`//false
System.out.println(str2==str5);`//true
System.out.println("str"+"ing"=="string");`//true as "str"+"ing" will be replaced by "string" at compile time only (constant)
Upvotes: 0
Reputation: 25419
Only string literals and constant expressions are guaranteed to be pooled. Since str1 + str2
is not a literal, it's up to the JVM whether or not the result will be interned. You can force it via calling intern()
as you have already found out.
This is defined in § 3.10.5 of the Java Language Specification:
A string literal is a reference to an instance of class
String
(§4.3.1, §4.3.3).Moreover, a string literal always refers to the same instance of class
String
. This is because string literals – or, more generally, strings that are the values of constant expressions (§15.28) – are “interned” so as to share unique instances, using the methodString.intern
.
Your second example, "str" + "ing"
, is a constant expression so it is guaranteed to be interned.
Also see the JavaDoc for String.intern
.
This is an attempt to explain what is going on. Well-written code should probably never rely on this but always use the equals
method. Any reasonable JRE will have a check like
if (this == other)
return true;
very close to the top of String.equals
so performance wise, it shouldn't matter.
Upvotes: 6
Reputation: 368
Always use equals method for comparing strings. The trouble about interning is that each version of JDK does it a bit differently, so I wouldn't have counted on that unless you want to call intern every time on the string.
Upvotes: 0