67

I have following lines of code to compare String. str1 not equal to str2, which is understandable since it compares object reference. But then why is s1 equal to s2?

String s1 = "abc";
String s2 = "abc";
    
String str1 = new String("abc");
String str2 = new String("abc");
    
if (s1==s2)
    System.out.println("s1==s2");           
else
    System.out.println("s1!=s2");
    
if (str1==str2)
    System.out.println("str1==str2");           
else
    System.out.println("str1!=str2");
    
if (s1==str1)
    System.out.println("str1==s1");         
else
    System.out.println("str1!=s1");

Output:

  s1==s2
  str1!=str2
  str1!=s1
starball
  • 20,030
  • 7
  • 43
  • 238
user84592
  • 4,750
  • 11
  • 55
  • 91
  • 13
    http://stackoverflow.com/questions/7144059/java-string-pool-object-creation , http://stackoverflow.com/questions/4033625/if-compares-references-in-java-why-does-it-evaluate-to-true-with-these-strin , http://stackoverflow.com/questions/6377058/string-reference , http://stackoverflow.com/questions/1903094/java-strings-and-stringpool –  Mar 14 '12 at 17:45
  • 1
    possible duplicate of [Using '==' instead of .equals for Java strings](http://stackoverflow.com/questions/3689952/using-instead-of-equals-for-java-strings) – Aillyn Nov 30 '12 at 16:15

6 Answers6

92

The string constant pool will essentially cache all string literals so they're the same object underneath, which is why you see the output you do for s1==s2. It's essentially an optimisation in the VM to avoid creating a new string object each time a literal is declared, which could get very expensive very quickly! With your str1==str2 example, you're explicitly telling the VM to create new string objects, hence why it's false.

As an aside, calling the intern() method on any string will add it to the constant pool, so long as an equivalent string isn't there already (and return the String that it's added to the pool.) It's not necessarily a good idea to do this however unless you're sure you're dealing with strings that will definitely be used as constants, otherwise you may end up creating hard to track down memory leaks.

Michael Berry
  • 70,193
  • 21
  • 157
  • 216
  • 2
    +1 but also worth noting that adding lots of Strings to the constant pool in general is a bad idea since it can cause difficult-to-detect memory leaks. Only do this for a small number fixed of Strings that are genuinely going to be used as constants (e.g. HashMap keys), never for arbitrary String data. – mikera Mar 14 '12 at 20:56
22

s1 and s2 are String literals. When you create a new String literal the compiler first checks whether any literal representing the same is present in the String pool or not. If there is one present, the compiler returns that literal otherwise the compiler creates a new one.

When you created String s2 the compiler returns the String s1 from the pool as it was already created before. That is the reason why s1 and s2 are same. This behaviour is called interning.

Michael Berry
  • 70,193
  • 21
  • 157
  • 216
Chandra Sekhar
  • 18,914
  • 16
  • 84
  • 125
  • I am slightly confused when you say that "compiler creates a new one". AFAIK, compiler is meant for creating the intermediate machine code and does not actually runs (hence creates) any object in memory. Did you mean that compiler _replaces_ string literals? Please clarify this. – peakit Mar 20 '12 at 18:41
  • I don't have any supporting documentation right now, but I believe @Chandra Sekhar was referring to the JIT or Just In Time compiler and not the javac compiler. – Robert Mar 20 '12 at 19:39
11

This phenomenon is due to String interning.

Basically, all string literals are "cached" and reused.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
5

As string is immutable in java, all the string literals cached for the reusability.

When you create String object using new() operator, it always create a new object in heap memory. On the other hand, if you create object using String literal syntax e.g. "Java", it may return an existing object from String pool (a cache of String object in Perm gen space, which is now moved to heap space in recent Java release), if it's already exists. Otherwise it will create a new string object and put in string pool for future re-use.

String s1 = new String("java");
String s2 = new String("java");
String s3 = "java";
String s4 = "java";

enter image description here

Please refer this link

Ramesh Papaganti
  • 7,311
  • 3
  • 31
  • 36
5

In Java, the same constant strings will be reused. So that s1 and s2 point to the same "abc" object and s1==s2. But when you use new String("abc"), another object will be created. So that s1 != str1.

Michael Berry
  • 70,193
  • 21
  • 157
  • 216
zsxwing
  • 20,270
  • 4
  • 37
  • 59
5

This is due to String literals being interned. On this matter, Java documentations says:

All literal strings and string-valued constant expressions are interned

And this explains why s1 and s2 are the same (these two variables point to the same interned string)

GETah
  • 20,922
  • 7
  • 61
  • 103