Reputation: 593
I have a scenario like this -
String s = "abc", t="abc"; //LINE 1
System.out.println(s==t); // definitely it would return true; //LINE 2
s=s+"d"; t=t+"d"; //LINE 3
System.out.println(s==t); // output would be false; but why??
s=s.intern(); t=t.intern();
System.out.println(s==t); // it would return true;
I wanted to know why the second print statement returned false. Please provide me any reference link which explains the same.
While creating t at line 1; intern was called and it pointed to "abc" why not intern was called at line 3?
Upvotes: 0
Views: 255
Reputation: 13456
Java Language Specification explicitly covers this particular situation. Here is a quote from chapter 3.10.5. "String Literals":
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 method String.intern.
As you can see, only constant expressions are interned. So, first four lines of your code are equivalent to:
String s = "abc".intern(), t="abc".intern();
System.out.println(s==t);
s=s+"d".intern(); t=t+"d".intern();
System.out.println(s==t);
Expressions s+"d"
and t+"d"
aren't constant and, thus, aren't interned.
JLS even provides an example with useful notes. Here is the relevant part:
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == ("Hel"+lo)));
}
}
Output: false
Note: Strings computed by concatenation at run time are newly created and therefore distinct.
Upvotes: 0
Reputation: 95588
String s = "abc", t="abc";
s == t
is true
because Java automatically interns String
literals. In this case the String
literal "abc"
has been interned and both s
and t
point to that same instance. Hence s == t
is true
.
s = s + "d"; t = t + "d";
Strings in Java are immutable. Hence what you are assigning to s
and t
are two new Strings
that have been constructed. Therefore they do not point to the same instance. This is why s == t
returns false
.
s = s.intern(); t = t.intern();
Here you have forcibly interned the string in s.intern()
. Since both s
and t
contain the same string values, the JVM sees that t
is the same and makes it point to the same interned-instance as s
. Hence s == t
is true
.
As a general note, establishing the equality of strings should be done via .equals()
and not ==
; ==
only compares references for reference-types and not values.
Upvotes: 4
Reputation: 34042
Strings are "special" Java objects.
The JVM tries to reuse the same references (that's why String s = "abc", t="abc";
causes s
and t
to point to the same instance), however, when working on instances (like t=t+"d") a new instance gets created, thus, the references are not the same
In order to compare strings you have to use the .equals()
method.
intern() causes to create a canonical representation out of the string pool inside the String class ( http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern%28%29)
Upvotes: 4
Reputation: 85789
Because when you concatenate String
s you generate a new object reference except when they are literal String
s.
Note that the intern
of both String
s point to the same literal String
object reference.
Upvotes: 0
Reputation: 24202
java strings are immutable.
that means that when you do something like s=s+"d"
youre actually creating a whole new string, and assigning it to s.
on top of that, the compiler does constant detection and allocation, so that when you write s="abc", t="abc"
the compiler re-uses the same reference and your code is effectively s=t="abc"
so you start with the exact same string instance (thanks to compiler optimization) and turn it into 2 identical yet different strings, at which point s==t
is false (s.equals(t)
would have been true, as it compares the contents and not the address in memory).
next up is intern(). what intern() does is looks up an identical string in the string cache and returns it. if it doesnt find an identical entry it places the argument provided into the cache and returns the argument. so s=s.intern()
places s into the string cache and returns it (so s
is unchanged) but the following call t=t.intern()
actually returns s
, so that s==t
again.
Upvotes: 6