10

Possible Duplicate:
What makes reference comparison (==) work for some strings in Java?

I know this has been asked before, but in spite of recommendations to use .equals() instead of the == comparison operator, I found that == works all the time:

String s1 = "Hello";
String s2 = "Hello";
System.out.println(s1 == s2); // true

Can anyone give me an example of the == operator failing?

Community
  • 1
  • 1
Aillyn
  • 23,354
  • 24
  • 59
  • 84
  • Marcos provided a [good example](http://stackoverflow.com/questions/767372/java-string-equals-versus/1251721#1251721) in an answer to the question you linked. – Matthew Flaschen Sep 11 '10 at 23:00
  • Related: http://stackoverflow.com/questions/9698260/what-makes-reference-comparison-work-for-some-strings-in-java/9698305#9698305 – Michael Berry Nov 20 '12 at 13:24

4 Answers4

40

This is because you're lucky. The == operator in Java checks for reference equality: it returns true if the pointers are the same. It does not check for contents equality. Identical strings found at compile-time are collapsed into a single String instance, so it works with String literals, but not with strings generated at runtime.

For instance, "Foo" == "Foo" might work, but "Foo" == new String("Foo") won't, because new String("Foo") creates a new String instance, and breaks any possible pointer equality.

More importantly, most Strings you deal with in a real-world program are runtime-generated. User input in text boxes is runtime-generated. Messages received through a socket are runtime-generated. Stuff read from a file is runtime-generated. So it's very important that you use the equals method, and not the == operator, if you want to check for contents equality.

zneak
  • 134,922
  • 42
  • 253
  • 328
  • 3
    A bit of an additional note, the reason "foo" == "foo" actually works, is because all literal strings are interned http://download.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#intern() – Matt Briggs Sep 11 '10 at 06:25
10

Can anyone give me an example of the == operator failing?

Example 1:

String s1 = new String("Hello");
String s2 = new String("Hello");
System.out.println(s1 == s2); // false

Example 2:

Integer a=1000,b=1000;
System.out.println(a == b); // false
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • 1
    Guess that will work. But aren't Strings immutable? As such, shouldn't they be interned? – Aillyn Sep 11 '10 at 05:45
  • Literal strings are interned. – Bruno Reis Sep 11 '10 at 05:46
  • 1
    "Hello" == "Hello" ==> true. However, new String("Hello") will allocate some memory for an object, and the same thing again will allocate some more memory, elsewhere, for another object. Since the "==" operator compares references, it will return false. – Bruno Reis Sep 11 '10 at 05:47
  • 3
    Small Integers (-127 .. 127) are also "interned". So the Integer example would actually return true for a = 100. (this is an implementation detail, however, I would not want to rely on it). – Thilo Sep 11 '10 at 06:17
  • 1
    @pessimopoppotamus - **only** String **literals** are interned automatically. Other String instances are interned only if the application calls `String.intern()` explicitly. (It is an efficiency thing: interning is expensive in a number of respects.) – Stephen C Sep 11 '10 at 06:50
4

When you do this, you are actually creating string literals:

String s1 = "Hello";
String s2 = "Hello";

The compiler finds identical string literals and then optimizes by keeping one instance in the heap and making all the variables in the stack point to it. So doing an == will return true because they point to the same memory address.

When you do this, you are creating string objects:

String s1 = new String("Hello");
String s2 = new String("Hello");

The instantiation will create unique space on the heap for each of these and the stack variables will point to those separate locations. Thus, these will be equal using .equals() because their values are the same, but they will not be equal using == because they are different objects in the heap memory space.

Javid Jamae
  • 8,741
  • 4
  • 47
  • 62
4

Seasoned Java developers rarely if ever use new String(String), but the problem arises in other cases as well. For example:

String hello = "Hello"
String hell = hello.substring(0, 4);
System.err.println("Hell" == hell);  // should print "false".

(Most String instances in a real-world applications are formed either by taking a substring of some other String, or by constructing it from an array of characters. Very few applications will only use String instances created as literals.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 1
    One reason to use "y = new String(x)" (where x is a string) is to allow garbage collection, when x is a substring of a very large string. If you just use "y = x" then the very large string can't get garbage collected as long as y is referenced. If you use "new String(x)" then a new string is created that doesn't reference the original large string. – Thomas Mueller Sep 11 '10 at 11:04
  • 4
    That is true, but in my experience it is rarely necessary. And if it is not necessary, then it is actually an anti-optimization. – Stephen C Sep 11 '10 at 13:14