1
public static void main(String[] args) {
    String str1 = "java";
    String str2 = str1.intern();
    String str3 = new String(str1.intern());
    System.out.println("hash1=" + str1.hashCode());
    System.out.println("hash2=" + str2.hashCode());
    System.out.println("hash3=" + str3.hashCode());
    System.out.println("str1==str2==>>" + (str1 == str2));
    System.out.println("str1==str3==>>" + (str1 == str3));
}

============================================output===>
hash1=3254818
hash2=3254818
hash3=3254818
str1==str2==>>true
str1==str3==>>false

=================================

Can anyone explain how == returns false even though s1 and s3 having same hashcode?

Rohit Gaikwad
  • 3,677
  • 3
  • 17
  • 40
  • 5
    This happens because a `String` is an `Object`, not a primitive. Use `.equals()` – Tibrogargan Nov 08 '16 at 06:02
  • Same `hashCode` does not mean the objects are identical (`==`), they need not even be equal (`.equals()`). – Henry Nov 08 '16 at 06:03
  • 2
    Because `==` compare the objects references, not the `hashCode` . – Umais Gillani Nov 08 '16 at 06:04
  • @UmaisGillani, I guess that memory reference value and hashcode value are different. Is it so? – Rohit Gaikwad Nov 08 '16 at 06:06
  • 1
    You need to use `.equals()`, but you could still have two strings that are not equal that have the same hash code. There are only 2^32 possible hash codes and many, many more possible strings than that. – ajb Nov 08 '16 at 06:08
  • Just FYI, I've never seen `String#intern` be a valid solution to a problem. Don't use it unless you know what you're doing and have an important reason to use it. – 4castle Nov 08 '16 at 06:08
  • 2
    To all people trying to close this as a duplicate of "How do I compare strings in Java?" I don't think it is. The OP seems to believe the same hash code implies the objects are equal (or identical). This is a different issue. – Henry Nov 08 '16 at 06:08
  • @Tibrogargan, thanks for help for making use of `equals` method, But I can't use this because, it was an interview question. So I need a proper reason for this. – Rohit Gaikwad Nov 08 '16 at 06:10
  • @RohitGaikwad ... awkward – Tibrogargan Nov 08 '16 at 06:13
  • @RohitGaikwad these are two different things, please have a look [Object reference and hashcode diff](http://stackoverflow.com/questions/4568896/difference-between-object-reference-and-object-hash-code). or correct me if i am wrong. – Umais Gillani Nov 08 '16 at 06:13
  • @Makoto Agreed, did I say something different? The same hash code does not imply equals. So you may get false even if you use `.equals()` instead of `==` (not in this example, but in general). Therefore it's not a duplicate. – Henry Nov 08 '16 at 06:16
  • I'll tentatively reopen this question since you're looking more for a proper reasoning to this. To avoid the direct spoiler, I'll abstain from answering, but the biggest clue would be in the source code for `String.equals`. – Makoto Nov 08 '16 at 06:17
  • `str3` is a new `String` - that is, not the same `String` object as `str1` or `str2`. Because you used `new` to create it, and the JVM did what you told it to do. – Dawood ibn Kareem Nov 08 '16 at 06:19
  • @RohitGaikwad Funnily enough, the Java documentation only implies that `==` should only be used for primitives, although it's probably more correct to say that `==` should only be used on `values`. Since the "value" of any Object is really a memory address, the result you get from comparing two objects with `==` makes perfect sense. If you want to get actual equivalence, you need to compare the contents of the Objects (using `.equals()`/`.hashCode()`) BTW, you shouldn't get hired. – Tibrogargan Nov 08 '16 at 06:23
  • @DavidWallace, thanks for this. Actually I know this concept of Strings in java. But the interviewer tried to deceive me why it returns false even though s1 and s3 have same hashcode. – Rohit Gaikwad Nov 08 '16 at 06:26
  • Well, if you understand that `s1` and `s3` are not the same object, then what is your question? – Dawood ibn Kareem Nov 08 '16 at 06:29
  • "If hashcodes of two objects are equals, that may not mean that objects are equals" – Viet Nov 08 '16 at 06:30

4 Answers4

3

Despite the comments above, I suspect that you already understand that == determines if two references point to the same object (or are both null), and that you should use equals() if you want to compare two strings for data-equality.

Rather, I think what you're missing is that the hashCode() method corresponds to the equals() method in this respect; it's based on the data in an object, and in fact, it's specified that classes should always implement hashCode() in such a way that if a.equals(b), then a.hashCode() == b.hashCode(). (Of course, there's nothing in the language that enforces this.) The analogue of == that you're looking for is the System.identityHashCode() method.

However, even there it should be noted that System.identityHashCode() does not guarantee that distinct instances will have distinct identity hash codes. (It can't, because it's possible to have more than 232 objects in a JVM at the same time . . . granted, not all JVMs support that; but nothing in the Java language specification forbids it.)

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • I agree on this about the guarantee. Just a counter question on this, does it mean `==` may return `true` sometimes in this case? As, sometimes it may give you the guarantee. – Rohit Gaikwad Nov 08 '16 at 06:39
  • 1
    @RohitGaikwad: No; `a == b` will only be `true` if `a` and `b` are the same instance (or if both are `null`). This means that `a == b` can be `false` even if `System.identityHashCode(a) == System.identityHashCode(b)`: the latter can have some false positives, but the former makes a firm guarantee. – ruakh Nov 08 '16 at 07:09
1

In a correct implementation of equals and hashCode you have the following implications for two objects a and b (that are not null):

if a == b then also a.equals(b)

if a.equals(b) then also a.hashCode() == b.hashCode()

Both implications cannot be reversed in general.

Henry
  • 42,982
  • 7
  • 68
  • 84
-1

For two Objects the == operator compares their pointer reference. So unless they are actually the exact same object it's never true.

Gandalf
  • 9,648
  • 8
  • 53
  • 88
-1

When you do:

String a = "xyz"

while creating the string, the JVM searches in the pool of strings if there already exists a string value xyz, if so 'a' will simply be a reference of that string and no new String object is created.

But if you say:

String a = new String("xyz")

you force JVM to create a new String reference, even if "xyz" is in its pool. and == compares the references. That's why you are getting the false result.

Umais Gillani
  • 608
  • 4
  • 9
  • Thanks for your answer, I know this concept of Strings in java. But I need an answer for why it returns false even though s1 and s3 have same hashcode. Here, hashcode is same. Does the memory reference value and hashcode value are different? I mean what == uses (reference value or hashcode value) I think its reference value. – Rohit Gaikwad Nov 08 '16 at 06:31
  • @RohitGaikwad yes these two are different things, as i mentioned the link in question's comment. `.equals` method compares the `hashCode` while `==` compares the references. please have a look [Object reference and hashcode diff](http://stackoverflow.com/questions/4568896/difference-between-object-reference-and-object-hash-code). – Umais Gillani Nov 08 '16 at 06:35
  • and `new String(` forces the JVM to create new String reference. that's why `==` will returns false. – Umais Gillani Nov 08 '16 at 06:36
  • 1
    The hash code of a `String` has no relationship at all to its address in memory. – Dawood ibn Kareem Nov 08 '16 at 06:37