1

I have the following code:

Circle c1 = new Circle();
Circle c2 = new Circle();
System.out.println(c1 == c2);

Which outputs False, as expected. This is because c1 and c2 are reference types and "==" checks if they refer to the same type (which they don't).

However, I recently tried this:

String a = "hello";
String b = "hello";
System.out.println(a == b);

Which for some reason outputs True. Why is this? String is a reference type and a and b refer to different memory locations. I was always taught that you need to use .equals() for this to work, which this does not!

See: https://ideone.com/CyjE49

UPDATE THIS IS NOT A DUPLICATE! I know the proper way to compare strings is using .eqauls()

UPDATE 2 This question may have an answer in: How do I compare strings in Java?, but the question there wasn't asking what I am asking and the answer just went in more detail than required.

Therefore searching with my same question (on Google or otherwise) means users won't be sent to that question or may dismiss it entirely due to the title of the question. Therefore it may be a good idea to keep this up for benefit of other users!

Community
  • 1
  • 1
Yahya Uddin
  • 26,997
  • 35
  • 140
  • 231
  • 1
    I agree with OP - this is not a duplicate of either of those questions. This is asking _why_ the reference equality does return true for two identical string literals. – davmac Oct 03 '15 at 19:22
  • 2
    You will find the answer here http://stackoverflow.com/questions/2486191/what-is-the-java-string-pool-and-how-is-s-different-from-new-strings. – yorlin Oct 03 '15 at 19:31
  • Yes this question may have an answer there, but the question there wasent asking that. Therefore searching with my same question, won't be sent there. Therefore it may be an idea to keep this up for benefit of other users! – Yahya Uddin Oct 11 '15 at 10:57

3 Answers3

7

Because string literals are intern'd, identical literals refer to the same object. Therefore, checking for reference equality between them will necessarily return true.

From the Java Language Specification (3.10.5):

Moreover, a string literal always refers to the same instance of class String. This is because 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.

In practice, the compiler will pool the string literals "early" and store only one copy in the compiled .class file. However, identical string literals from separate class files will still compare equal using == since the literals are still intern'd when the classes are loaded.

If, on the other hand, we properly apply your example with Circle to String, we would have:

String a = new String("hello");
String b = new String("hello");
System.out.println(a == b);  // will print false!

In this case we explicitly create new objects, so they cannot be equal references.

Any string constructed by means other than a literal or other constant string expression will also not necessarily compare reference-equal with an identical string. For example:

String a = "hello";
String b = "hello";
System.out.println(a.substring(0,3) == b.substring(0,3));  // may print false!
davmac
  • 20,150
  • 1
  • 40
  • 68
2

String interning. Since both a and b are constants with the same value, the compiler takes advantage of the String's immutability to have both variables refer to the same string and thus save space. Therefore == returns True, since they're effectively the same object.

Mauricio
  • 1,683
  • 12
  • 18
1

In this case, "hello" is treated as a constant which is assigned to a and b. So here == actually returns true. If you do this:

String a = new String("hello");
String b = new String("hello");
System.out.println(a == b);

You will get false.

Ridcully
  • 23,362
  • 7
  • 71
  • 86