Avoid comparing strings with == in Java

While beginning development in Java, especially if coming from a .NET background (but not necessarily) you might do string comparison with == in Java. Don’t do it. It will compare the string instances and not their effective value.
You might even try it first to check if == really works, testing it in a wrong manner like so :

public static void main(String[] args) {

    String s1 = "Abc";
    String s2 = "Abc";

    System.out.println("s1 == s2 -> " + (s1 == s2));
}

This will output

s1 == s2 -> true

.. which might lead you to believe this works. This does return the correct value because of a feature present in Java and .NET called string interning (not specific to Java or .NET).

Try to obtain a string instance dynamically like concatenating two existing instances and see how things don’t work anymore :

public static void main(String[] args) {

    String s1 = "Abc";
    String s2 = "Abc";

    // new lines :
    String capitalA = "A";
    String bc = "bc";
    String s3 = capitalA + bc;

    System.out.println("s1 == s2 -> " + (s1 == s2));
    // new line :
    System.out.println("s1 == s3 -> " + (s1 == s3));
}
s1 == s2 -> true
s1 == s3 -> false

Weird, huh? That’s because at compile time there are four distinct strings generated : “Abc” (once, even if referred twice), “A” and “bc”. The “Abc” instance obtained by joining “A” and “bc” will be generated at runtime and, of course, it will be a different instance than the first “Abc” instance. That’s why the result of the == operator comparison will be false.

But the compiler can be smarter than you might expect. How’s that? Here’s how :

public static void main(String[] args) {

    String s1 = "Abc";
    String s2 = "Abc";

    String capitalA = "A";
    String bc = "bc";
    String s3 = capitalA + bc;

    // new line
    String s4 = "A" + "bc";

    System.out.println("s1 == s2 -> " + (s1 == s2));
    System.out.println("s1 == s3 -> " + (s1 == s3));
    // new line
    System.out.println("s1 == s4 -> " + (s1 == s4));
}

.. resulting in :

s1 == s2 -> true
s1 == s3 -> false
s1 == s4 -> true

The compiler inferred the result of the string concatenation in the s4 initialization and then interned the resulted string, detected the already existing “Abc” instance and reused it.

Alright, that’s not the right way to do it, the correct way to do it is to use the .equals(String s) instance method of the String class. Like so :

public static void main(String[] args) {

    String s1 = "Abc";

    String capitalA = "A";
    String bc = "bc";
    String s2 = capitalA + bc;

    System.out.println("s1.equals(s2) -> " +  s1.equals(s2));
}

This works nice :

s1.equals(s2) -> true

All’s well until we teak things a bit :

public static void main(String[] args) {

    String s1 = null;
    String s2 = null;

    System.out.println("s1.equals(s2) -> " +  s1.equals(s2));
}

Guess what, it’s not “true” that’s being displayed but the stack trace of a NullPointerException. Your solution might be some weird ternary expression (yuck) that looks like so :

public static void main(String[] args) {

    String s1 = null;
    String s2 = null;

    boolean b = s1 == null ? s2 == s1 : s1.equals(s2);
    System.out.println(b);
}

You can extract this expression into a static method in a helper class if you find yourself doing this often.

As a final aspect to consider, if one of the two strings is a constant value you can still use equals on that one like so :

public static void main(String[] args) {

    String s1 = getData();
    String s2 = "someValue";

    System.out.println(s2.equals(s1));
    System.out.println("someOtherValue".equals(s1));
}
  1. There is the possibility to apply “intern” method over any dynamic string.

    Maybe you should also cover Comparator and Comparable interfaces. They do provide quite useful functionality.

  2. Even in .NET we are taught not to compare strings with ‘==’ and without including culture and case iinformation.

    I always use:
    string.Equals(s1,s1,StringComparison.CurrenCultureIgnoreCase)

  3. I agree with Alex. Are you sure there are no static methods on a string object somewhere in Java? Seems like a terrible oversight.
    Also, anything like extension methods in Java?

  4. Of course there is no static method or other kind of helper. It’s effing Java, what did you expect…

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.