views:

324

answers:

5

As it is stated the == operator compares object references to check if they are referring to the same object on a heap. If so why am I getting the "Equal" for this piece of code?

public class Salmon {
 public static void main(String[] args) {

  String str1 = "Str1";
  String str2 = "Str1";

  if(str1 == str2){
   System.out.println("Equal");
  } else {
   System.out.println("Not equal");
  }
 }
}
+3  A: 

This code won't print Equal.
But if the two strings were the same, this case would be special.

Now that you've updated your code, it is the case :

A simple (but not totally exact) explanation is that the compiler see that the two strings are the same and do something like :

String str1 = "Str1";
String str2 = str1;

What really happens here is that the compiler will see the literal string and put it in the "String literal pool".

As a String can't be modified (it's immutable) the literal values of Strings (those found during compilation) are put in a "pool".
This way, if two different literal strings which have the same content (like in this particular case), the memory isn't wasted to store "Str1" and "Str1" two times.

Colin Hebert
I'm sorry, I've added corrections to the code example.
AndroidNoob
+3  A: 

Java stores all Strings in a string table internally during a run. The references to the two strings are identical because in memory they're stored in the same place. Hence, Equal.

Your statement is right, that == compares object references. Try the same thing with any other class but Strings and you won't get the same result.

Tenner
It does? can you give me a reference to back this claim?
Richard J. Ross III
aioobe gives a better explanation, as this behavior is not guaranteed. And it also applies only to string literals, not to every string in a program.
Joey
From the Java API docs: "All literal strings and string-valued constant expressions are interned." See http://download.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#intern%28%29 Note that only constant strings will be automatically interned. You can intern dynamically created Strings by involing String.intern()
Hannes de Jager
+27  A: 

The program will print Equal. (At least using the Sun Hotspot and suns Javac.) Here it is demonstrated on http://ideone.com/fXM9G

This is due to the fact that string-literal constants are stored in a string pool and string references may be reused.

Further reading:


This however:

public class Salmon {
 public static void main(String[] args) {

  String str1 = "Str1";
  String str2 = new String("Str1");

  if(str1 == str2){
   System.out.println("Equal");
  } else {
   System.out.println("Not equal");
  }
 }
}

Will print Not equal since new is guaranteed to introduce a fresh reference.

So, rule of thumb: Always compare strings using the equals method.

aioobe
+1 for linking to ideone.com. I wanted a webapp like this for a long time. Even thought of writing it myself but there it is.
Alexandre Jasmin
For completeness `new String("Str1").intern()` will print "Equal" also :)
OscarRyz
@OscarRyz, Good point. Thanks! :-)
aioobe
A: 

Comments above have summed it up pretty well.

I don't have a Java environment handy, but attempting the following should clarify things for you (hopefully this works as I anticipate).

String str1 = "Str1";
String str2 = "Str"; str2 += "1";

Should now print Not equal

jon_darkstar
+1  A: 

People, you are forgetting that the process of placing literal strings in the pool is called "interning". The class String has a method called intern(). This method puts any string into the pool, even if it is not in the pool initially (not literal). This means that code like this:

String a = "hello";
String b = new String("hello");
b = b.intern();

System.out.println(a == b);

will print "true". Now, why would someone need this? As you can imagine, string comparison a.equals(b) might take a long time if strings are the same length but different close to the end. (Just look at the .equals() source code.).

However, comparing references directly is the same as comparing integers (pointers in C speak), which is near instant.

So, what does this give you? Speed. If you have to compare the same strings many, many times, your program performance will benefit tremendously if you intern these strings. If however you are going to compare strings only once, there will be no performance gain as the interning process itself uses equals().

I hope this explains this.

thanks

ipolevoy