javastringequality

How do I compare strings in Java?


I've been using the == operator in my program to compare all my strings so far. However, I ran into a bug, changed one of them into .equals() instead, and it fixed the bug.

Is == bad? When should it and should it not be used? What's the difference?


Solution

  • == tests for reference equality (whether they are the same object).

    .equals() tests for value equality (whether they contain the same data).

    Objects.equals() checks for null before calling .equals() so you don't have to (available as of JDK7, also available in Guava).

    Consequently, if you want to test whether two strings have the same value you will probably want to use Objects.equals().

    // 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 
    
    // ... string literals are concatenated by the compiler
    // and the results are interned.
    "test" == "te" + "st" // --> true
    
    // ... but you should really just call Objects.equals()
    Objects.equals("test", new String("test")) // --> true
    Objects.equals(null, "test") // --> false
    Objects.equals(null, null) // --> true
    

    From the Java Language Specification JLS 15.21.3. Reference Equality Operators == and !=:

    While == may be used to compare references of type String, such an equality test determines whether or not the two operands refer to the same String object. The result is false if the operands are distinct String objects, even if they contain the same sequence of characters (§3.10.5, §3.10.6). The contents of two strings s and t can be tested for equality by the method invocation s.equals(t).

    You almost always want to use Objects.equals(). In the rare situation where you know you're dealing with interned strings, you can use ==.

    From JLS 3.10.5. String Literals:

    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.

    Similar examples can also be found in JLS 3.10.5-1.

    Other Methods To Consider

    String.equalsIgnoreCase() value equality that ignores case. Beware, however, that this method can have unexpected results in various locale-related cases, see this question.

    String.contentEquals() compares the content of the String with the content of any CharSequence (available since Java 1.5). Saves you from having to turn your StringBuffer, etc into a String before doing the equality comparison, but leaves the null checking to you.