[Java] Using == to compare Strings

This is a very common mistake, probably because of the misinformation about what the == operator really does. This mistake is about using == instead of equals() to compare String contents.

When should I use them?

  • == is used to compare values of primitive types (int, float, boolean, …), but it’s also used to compare object references (memory addresses).
  • equals() method should be used to compare contents (information) of Objects. Note that the initial implementation returns the same as obj1 == obj2, in other words, it compares references. But this method is generally override by programmers to compare object contents, and this is the case of String (remember that String is an Object, not a primitive).

In conclusion, to compare String contents we must use equals(). But it is worth noting that Strings content can be also compared with == operator in some situations. Let’s see some examples:

// These two have the same value
new String("test").equals("test") --> true 

// ... but they are not the same object
new String("test") == "test" --> false 

// ... neither are these
new String("test") == new String("test") --> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" --> true 

// concatenation of string literals happens at compile time,
// also resulting in the same object
"test" == "te" + "st" --> true

// but .substring() is invoked at runtime, generating distinct objects
"test" == "!test".substring(1) --> false

Why does line 12 and 16 evaluate to true? Because of String interning. What happens in these cases is that the compiler interns String literals in memory at compile time (this is done to save memory). In line 12 and 16 the String literals that are beign compared are in the same memory location, so the comparison with == operator returns true.
However, this is not recommended unless you want better performance (comparing memory addresses is a lot “cheaper” than a loop) and you are sure that the Strings being compared are interned literals.