views:

216

answers:

5
public class A {

    static String s1 = "I am A";

    public static void main(String[] args) {
        String s2 = "I am A";
        System.out.println(s1 == s2);
    }
}

Above program outputs "true". Both are two different identifiers/objects how the output is "true" ?

My understanding is that the JVM will create different reference for each object, if so how the output is true?

+1  A: 

You aren't comparing the content of the strings. You are only comparing the object's references. You should use the equal method (which is a member of the String class). Either that or you can use the compareTo method (also under the same String class) to check if the return value is zero.

Please note the text above was more of a strong suggestion to the orginal state of the question as that it appeared the OP was unaware of the actual process going on behind the scenes.

The other guys suggesting internalling was right. To answer this question I didn't have enough time to go to the Java Puzzlers book. I did suspect something about setting the same reference at compile time, but I didn't know how to find a reference to that either.

monksy
If I compare the contents then the answer is definitely "true". But here both are two different variables, won't jvm create two different references ?
novice
@Felix. Nope, he is comparing references, and the output is true - which is exactly the slightly surprising result that has prompted this question.
Michael Borgwardt
Why have you guys marked down a correct answer ?
Steve De Caux
@Steve De Caux: I didn't downvote, but I think people downvoted because this doesn't address *why* the string references are the same. I think the OP knows the difference between == and equals, but was confused by two string objects were being treated as the same one. This answer, though it has correct content, doesn't answer the question at all.
Tom
It seems to me a wierd when this guy gets way downvoted for waffling close to the topic, when an answer that is completely wrong actually had some upvotes when I first read this question.
Steve De Caux
@Steve : Thats what I thought. IMO: Down votes say "wrong content" I guess people don't realize that downvoting costs rep.
monksy
@Steve De Caux: I know :-). Answers like this I tend to just leave alone. The author of answers like these tend to just misread the question or not realize what the important part of the question is. I tend to reserve my downvotes for posts that have totally wrong information, or are way off target.(For example, Pavel's answer).
Tom
Check the edits... The content of the question changed after I posted this.
monksy
@steven: I think the question was clear the first time around. The OP was asking why the output was true (he seemed surprised at this because he had two different variables... he knew the difference between equals and ==... just didn't know why the two "different" strings were ==).
Tom
What I find frustrating is that now when people come to this page (for the most part) they will only upvote the accepted answer. It's pretty tough to submit a well-thought-out or well-written answer when it comes after another answer already got a bunch of upvotes or has been accepted.
Tom
My point is that during the first iteration of the question he did not mention that he understood the deal with the references, so I chimed in and mentioned that it was about references... I then went out to check why this corner case might exist.
monksy
+1 I think that the answer is correct, at least for the original question. And still valid for the actual version of the question, maybe not a direct answer, but at least a complement for thoose reader who don't know the correct use of `==` and `equals`. Maybe @steven should edit the answer to reflect this (and enable the deletion of the *old* downvotes)
Carlos Heuberger
'internalling' isn't a word.
Pete Kirkham
+17  A: 

Java manages a String literal pool. It reuses these literals when it can. Therefore the two objects are actually the same String object and == returns true.

I believe this is called string interning: String interning

Neil Foley
For information about the string pool, have a look at wikipedia: http://en.wikipedia.org/wiki/String_interning (+1 same idea)
Felix Kling
Yep, string literals are automatically interned, as per the intern method API - http://java.sun.com/javase/6/docs/api/java/lang/String.html
Ash
It's not just literals that are interned, but also compile-time constants.
Michael Borgwardt
Just please, please, please... as my answer points out... do not depend on this fact. Use `equals` when that's what you mean :-). I always get nervous when people post things about String interning so nonchalantly... Obviously the answer is correct and I do not dispute that, but I'd like to emphasize that while it explains the answer, it isn't something that should be relied on (as Josh Bloch points out, it is an implementation detail, not a programmer's tool).
Tom
Something mandated in the language spec is hardly and implementation detail, but I agree: while you can depend on literals being interned, you should not depend on the strings you use being literals - that can too easily change.
Michael Borgwardt
+5  A: 

Because the Java Language Specification says:

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.

Michael Borgwardt
+6  A: 

== checks that the variables are pointing at the exact same instance of an object. The two string literals you have created point to the same place in memory and therefore the are equal. String literals are interned so that the same string literal is the same object in memory.

If you were to do

String s = new String("foo");
String t = new String("foo");

Then == would return false and s.equals(t) would return true.

Jeff Foster
+4  A: 

It's because of a memory optimization performed by the compiler... namely, String constants (ie - Strings made by the same String literal) use the same String object since Strings are immutable. The == operator just checks that two objects are the same actual object.

If you can grab a hold of the book Java Puzzlers by Joshua Bloch and Neal Gafter, and look at puzzle 13, "Animal Farm"... he has great advice on this issue. I am going to copy some relevant text:

"You may be aware that compile-time constants of type String are interned [JLS 15.28]. In other words any two constant expressions of type String that designate the same character sequence are represented by identical object references... Your code should rarely, if ever, depend on the interning of string constants. Interning was designed solely to reduce the memory footprint of the virtual machine, not as a tool for programmers... When comparing object references, you should use the equals method in preference to the == operator unless you need to compare object identity rather than value."

That's from the above reference I mentioned... pages 30 - 31 in my book.

Tom
I mentioned this [granted I didn't mention why it did it], and I've gotten voted down for it.
monksy
+1 For mentioning Puzzlers and an explanation why
monksy