0

I recently went back to the String comparisons in Java and tried this:

String s = "hello";
System.out.println(s == "hello");
System.out.println(s.equals("hello"));

When I run it with jdk 19.0.1, Both expressions evaluate to true despite IDE warnings.

This is obviously against all my intuition, as I've been told since my very first day programming in Java that the first expression should be evaluate to false because they are different objects. My best guess is that Java has done some optimization at some point to override String comparison with ==, only I would like to know when did they do that.

Does anyone remember in which Java version has this optimization been done? Thanks.

sfeng
  • 93
  • 1
  • 7
  • 6
    Since always, if you want reference equality, which you almost never do. "*because they are different objects*" They're not. Both refer to the same interned string literal in the string constant pool. Same object. – Michael Jan 10 '23 at 16:12
  • 1
    this link might give more details - https://www.geeksforgeeks.org/difference-between-and-equals-method-in-java/ – Neeraj Jan 10 '23 at 16:13
  • 2
    the reason is that the string literal `"hello"` is known at compile time and thus ends up in the interned string pool. `s` is a reference to it. Since the references are the same, the `==` returns true. This would be different if you read that `"hello"` in line 2 from stdin or a file instead of using the same compile time constant. – f1sh Jan 10 '23 at 16:16
  • 1
    "Since always". Indeed, this is not an optimization. Rather it is a behavior that is **mandated** by the Java Language Specification. JLS 3.10.5 states: *"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.29) - are "interned" so as to share unique instances, as if by execution of the method String.intern (§12.5). "* – Stephen C Jan 10 '23 at 16:16
  • Curious, as this is not the way I've been told by my profs when he taught me Java. I guess he got it confused with C languages. Thanks. – sfeng Jan 10 '23 at 16:18
  • 1
    Either he was confused ... or you didn't hear / understand him correctly. Lets be fair :-) – Stephen C Jan 10 '23 at 16:19
  • @StephenC fair enough :-) I do still have his slides though – sfeng Jan 10 '23 at 16:20

1 Answers1

1

You are correct that == operator in Java will only return true if both references are pointing to the exact same object.

Now for why does s == "hello" return true for your example it has to do with how the Java compiler works.

In Java all strings are immutable. This means the objects themselves can not be changed. When you update the contents of a string in Java a new string object is created.

This allows the Java compiler to save memory at runtime by implementing string interning. Any string that is defined in the source code as a literal is placed in a string intern pool. When adding a string literal to this pool the complier checks if that string is in the pool and if yes returns a reference to the existing string. This means if you use the same string literal multiple times in the source code it is only stored once in memory.

In your example you use the string literal "hello" three times. When compiled all 3 string literals become the same string object. This is why in your example s == "hello" returns true.

Using == is bad practice when comparing strings in Java. It happens to "work" in your example because of how your example code is written and how the Java compiler works.