2

Can some one help me if I'm checking the reference of the String then what would be the exact answer and why?

String s = "java"; 
String s1 = "world";   
String s2 = "javaworld";  
String s3 = s.concat(s1); 
String s4 = s+"world";    
String s5 = "java"+"world"; 

why it gives true and false even though the hashCodes are same for s2,s3,s4,s5..

Boolean b  = s2==s3;   //'it gives false'
Boolean b1 = s3==s4;   //'it gives false'
Boolean b2 = s2==s4;   //'it gives false'
Boolean b3 = s2==s5;'  //'it gives true'
Vicky Thakor
  • 3,847
  • 7
  • 42
  • 67
  • to check equality do str1.equals(str2). – venkat Mar 04 '16 at 10:07
  • Reopened: to give folk more time to find a more targetted duplicate. – Bathsheba Mar 04 '16 at 10:08
  • See http://stackoverflow.com/a/9698305/1183192 – stevecross Mar 04 '16 at 10:09
  • There's probably a better duplicate: one that talks about compile time evaluable constant expressions, string interning, and reference comparisons – Bathsheba Mar 04 '16 at 10:10
  • Why do so many people think that their "I don't understand String pool/constants" question is unique? Please do some research first and find one of the hundred questions about this topic, before you post your own one. – Tom Mar 04 '16 at 10:14
  • @Tom - I agree with you. But there are some people who jump to close questions just because they see *comparison* and *String* tags :P – TheLostMind Mar 04 '16 at 10:20
  • 1
    @TheLostMind There are so many questions about String comparison like [this](http://stackoverflow.com/questions/34509566/in-case-of-string-concatenation-in-java) or [this](http://stackoverflow.com/questions/14150628/string-constant-pool-java), so it is quite hard to understand, why there are still new questions with this topic and why they still get upvotes (how does this question can show _any_ research?). – Tom Mar 04 '16 at 10:30
  • @Tom - Yes. *finding the right dupe* is the problem :P – TheLostMind Mar 04 '16 at 10:32
  • @TheLostMind So you're suggesting a canonical Q&A for this topic, with a descriptive title, which covers all facts (reference comparison, constant pool, what `equals` and `hashCode` do in `String` and how the compiler treats constant String concatenation (either `"blub" + "blub"` or `final String s = "blub"; String s2 = s + "blub"`)? :D – Tom Mar 04 '16 at 10:45
  • @Tom - I am not sure if that would help either. (sadly) – TheLostMind Mar 04 '16 at 11:16
  • @TheLostMind It would help to find the duplicate to "hammer" such questions. – Tom Mar 04 '16 at 11:55
  • @Tom - Yes. Probably. – TheLostMind Mar 04 '16 at 14:34

3 Answers3

3

why it gives true and false even though the hashCodes are same for s2,s3,s4,s5..

hashCode() and equals() are overridden for String class to ensure that 2 different Strings with the same value are equal. They are not the same, but they are equal. Try System.identityHashCode() for each String and see the actual hashCodes (which are not overridden).

s2 == s5 is true because "java" + "world" is changed to one String "javaworld" by the compiler.

TheLostMind
  • 35,966
  • 12
  • 68
  • 104
0

This occurs because of string interning in Java.

I will try to explain this using a simpler example. Please let me know if you need elaboration.

String a = "hello";  // "hello" created in object pool
String b = "hello";  // "hello" found in object pool, b references the same string object
System.out.println(a == b);  // prints true

This is because when you assign a literal to a String, "hello" is stored in the string literal pool. Anytime you use the literal "hello" it points to the same location in the pool. If you use a constructor however you will get false, because the String objects will have different memory addresses.

A 'safer' way to compare strings is using the equals() method. If you want to avoid interning from occuring, instead of initializing a string like this String a = "hello";, do this String a = new String("hello");

The second approach forces a new string object to be created.

Another note. Using constructors does ensure that two separate declarations are made. So, now we have two separate objects in the pool that contain the string "hello" But, calling the intern() function ensures that there is only one copy of "hello" in the pool stack and that both the objects point to it. So, again, an equality check would yield true.

Another small note. This part concerns using .equals() et al., over ==. Post interning, of course, == is ‘faster’ than equals() [since you are checking pointer references in == vs you are comparing string based on characters in .equals()]. So, if you need speed, you can compare strings by reference (== is faster than equals) (interning takes time though). Obviously, there are multiple side effects to this, which might not be within the scope of this post.

Debosmit Ray
  • 5,228
  • 2
  • 27
  • 43
0

Equality operator checks whether the object references compared refer to the same object or literal.

Now, Java VM uses a pool for string literals and uses it for comparisons between literals. Because of that, direct operations on literals such as plus will lead to string literals and any instance of them refers to the same literal, in a sense, as the compiler reasons it is about the same literal:

"foo" + "bar" == "foobar" // true

However, if you apply operations that generate new String objects as a result (such as String.concat) then this leads to different String objects:

"foo".concat("bar") == "foobar" //false, object implicit comparison with literal

What is suggested is that if you want to compare two Strings in values, then use String.equals method:

"foo".concat("bar").equals("foobar") //true

Nick Louloudakis
  • 5,856
  • 4
  • 41
  • 54