9

Say you have three strings,

String s1 = "string one";
String s2 = new String("string one");
String s3 = "string one";

I know it is true that s1 == s2 is false, but I read somewhere that s1 == s3 is true. Is this correct? Why or why not?

Charles
  • 50,943
  • 13
  • 104
  • 142
Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
  • 2
    Whether it is or not may be of passing interest, but you should not be doing it. `==` is for _object identity,_ not string comparisons. – paxdiablo Sep 20 '11 at 02:23
  • @paxdiablo: If you deal exclusively with string literals, it's okay to use `==`. But having to document that is generally such a pain that it's easier to just use `equals()` across the board. – C. K. Young Sep 20 '11 at 02:25
  • 1
    yeah, i know about all that. i've been programming in java for years and was just wondering :). it doesn't seem like it should be like that... – Alex Lockwood Sep 20 '11 at 02:26
  • possible duplicate of [Java String.equals versus ==](http://stackoverflow.com/questions/767372/java-string-equals-versus) – Miserable Variable Sep 20 '11 at 02:26
  • @HemalPandya: No, not a duplicate. That question refers to whether to use `equals`; this question asks when `==` will actually work reliably. – C. K. Young Sep 20 '11 at 02:30
  • 2
    This has been rocked to death on SO http://stackoverflow.com/search?q=compare+string+equal+java – Mob Sep 20 '11 at 02:58

3 Answers3

22

String literals are interned automatically. Hence s1 == s3 is true. Strings can either be created in the string constant pool or they can be created in the heap space. If you intern a string created in the heap, the string will be in the string constant pool.

When you create a string literal (String s1 = "string one"), the string is created in the string constant pool. Additionally, the string constant pool doesn't store duplicates. So when you say,

String s1 = "string one";
String s3 = "string one";

Both s1 and s3 will be pointing to the same instance of the string in the string constant pool. So s1.equals(s3) will be true. And s1 == s3 also is true; since both the pointers are the same.

However, when you instantiate a string using the "new" constructor

String s2 = new String("string one");

then s2 is created in the heap space. The heap space is a different area of memory than the string constant pool

So while s1.equals(s2) is true, s1 == s2 is false; since they will be pointing to different areas of memory.

However, you can convert a string created using the "new" constructor to make it move to the string constant pool by invoking the intern() function. So s2.intern() will return a string in the string constant pool; although s2 was originally created in the heap.

Basanth Roy
  • 6,272
  • 5
  • 25
  • 25
  • I believe this is only true within a compilation units? That is, I do not believe the more general: `A.x == B.x` is necessarily true. –  Sep 20 '11 at 02:17
  • 2
    -1 for the misleading, meaningless first sentence and no mention of string interning. – Matt Ball Sep 20 '11 at 02:18
  • 1
    @matt, i was typing and saving.. I do mention intern() in the end. – Basanth Roy Sep 20 '11 at 02:19
  • @rationalSpring: Matt's point was that interning should be the _main_ point of the message, not an afterthought. – C. K. Young Sep 20 '11 at 02:21
  • What happens when s3 is modified?? will it modify s1 also or created as another string in string constant pool?? – vivek_jonam Sep 20 '11 at 02:24
  • 2
    @vivek_jonam: Java strings are immutable. You can rebind `s3` to a new string, of course, but that will not affect the string `s1` is bound to. – C. K. Young Sep 20 '11 at 02:26
  • @Chris Jester-Young Hmm... I always thought it was baked into the class itself. Oh well :) –  Sep 20 '11 at 02:27
  • 1
    @pst: Each `.class` file has its own string constant pool (so you will see duplication if you look at the same string literal across two `.class` files), however, on class load, everything in the string constant pool is interned, so equivalent strings will refer to the same string object. – C. K. Young Sep 20 '11 at 02:28
4

Yes, that is true, because string literals are all interned. Read the documentation for String.intern() for more details.

As a consequence, these are all the same object (and will compare equal with ==):

s1
s3
s1.intern()
s2.intern()
s3.intern()
C. K. Young
  • 219,335
  • 46
  • 382
  • 435
1

above is HOW.

and You should know why.

A) string varaible declared in compile time ref to constant in constant pool

B) string varaible result by method ref to Object in heap space .

it all because JVM specfication and it's memory design.

A) is because strings are immutable。when java compile class and jvm load class , jvm found one String variable declared by your in coding time。 cause it is constant, jvm put the constant to "Runtime Constant Pool" memory area. and, constant is unique.

B) is verysimple. because jvm runtime variable use heap space.

swanliu
  • 781
  • 3
  • 8