views:

321

answers:

6
String s1 = "BloodParrot is the man";  
String s2 = "BloodParrot is the man";  
String s3 = new String("BloodParrot is the man");  

System.out.println(s1.equals(s2));
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1.equals(s3));

// output
true
true
false
true

Why don't all the strings have the same location in memory if all three have the same contents?

+3  A: 

You explicitly call new for s3 and this leaves you with a new instance of the string.

sharptooth
Oh, so the only difference is the use of the "new" keyword. So the strings that don't use the new keyword are not instances of a string object?
BloodParrot
They are instances, but they may not necessarily have dedicated buffers.
sharptooth
+1  A: 

The new keyword always makes a new string.

More detail here.

Robert Grant
+1  A: 

Why don't all the strings have the same location in memory if all three have the same contents?

Because they are different strings with same content!

Bharani
String s1 = "BloodParrot is the man";String s2 = "BloodParrot is the man";s1 == s2 => trueIt seems that s1 and s2 are the SAME strings.
Nicolas Dorier
Yes. Sorry. I was wrong! :(
Bharani
Those two *are* identical, pointing to the same address. Only s3 is different, because it is explicitly created as a new string.
erickson
There is no guarantee that s1 and s2 will be the same object.
Steve Kuo
+11  A: 

Java only automatically interns String literals. New String objects (created using the new keyword) are not interned by default. You can use the String.intern() method to intern an existing String object. Calling intern will check the existing String pool for a matching object and return it if one exists or add it if there was no match.

If you add the line

s3 = s3.intern();

to your code right after you create s3, you'll see the difference in your output.

See some more examples and a more detailed explanation.

This of course brings up the very important topic of when to use == and when to use the equals method in Java. You almost always want to use equals when dealing with object references. The == operator compares reference values, which is almost never what you mean to compare. Knowing the difference helps you decide when it's appropriate to use == or equals.

Bill the Lizard
+2  A: 

Creating a String is actually a fast process. Trying to find any previously created String will be much slower.

Consider what you need to do to make all Strings interned. You need to search a set of all previously constructed Strings. Note this must be done in a thread-safe manner, which adds overhead. Because you don't want this to leak, you need to be using some form of (thread-safe) non-strong references.

Of course, you can't implement Java like this because the library unfortunately exposes constructors for Strings and most other immutable value objects.

Tom Hawtin - tackline
+1  A: 

There is a method called String.intern which, essentially, takes all Strings that are the same and puts them into a hash table (I am sort of lying, but for this it is the concept that matters, not the reality).

String s1 = "BloodParrot is the man";  
String s2 = "BloodParrot is the man";  
String s3 = new String("BloodParrot is the man").intern();  

System.out.println(s1.equals(s2));
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1.equals(s3));

should have them all being "true". This is because (and I am lying a bit here again, but it still only matters for the concept not reality) String s1 = "BloodParrot is the man"; is done something like String s1 = "BloodParrot is the man".intern();

TofuBeer