Java Essentials: Understanding String Equality

 Photo by  Kirsten Carr  on  Unsplash

Photo by Kirsten Carr on Unsplash

Overview

In this article, we'll demonstrate how to compare strings in Java for equality and discuss some of the common pitfalls developers encounter along the way.

Using the equals() method

The String class contains an equals() method that's used to determine whether two strings are the same.  It returns a boolean.

Let's check out some code that uses the method:

Object obj = new Object();
    
String test1 = obj.toString();
String test2 = obj.toString();

System.out.println(test1.equals(test2)); // true

Sometimes, we may not care about case sensitivity.  We can use the equalsIgnoreCase() method in this situation:

String name1 = "Amir";
String name2 = "aMiR";

System.out.println(name1.equalsIgnoreCase(name2)); // true

Avoiding Exceptions with equals()

When comparing a string variable to a literal, we can write it a couple different ways:

String name = "Amir";
System.out.println(name.equals("Amir"));  // true
System.out.println("Amir".equals(name));  // true

Notice on line 3 how we swapped the order of the string literal and variable.   This is legal and actually the preferred approach over line 2.

Why?

Because it will not throw a NullPointerException if our name variable happens to be null.   It will simply return false which is usually what we want.

Let's take a look at some code that demonstrates this fact:

String name = null;
System.out.println("Amir".equals(name)); // false
System.out.println(name.equals("Amir")); // NullPointerException

Why not use the == operator?

While the == operator can be used safely to compare primitive integers, it is a mistake to use it on strings. 

When the operands are objects, the == operator compares their references, or where they are stored in memory.  It does not check the value stored in those objects.

Let's create an object and get the String representation of it so we can see how the operator behaves.

Object obj = new Object();
    
String test1 = obj.toString();
String test2 = obj.toString();

System.out.println(test1 == test2); // false

Notice that we assigned both strings the same value, but our equality check still returned false.

The operator is checking to see if they are the same object in memory which they are not.  

String Literals Caveat

Confusing matters is how Java behaves when the == operator is used on string literals.  

String name1 = "Amir";
String name2 = "Amir";

System.out.println(name1 == name2); // true

The operator actually behaves as expected and returns true! 

The reason for this is that Java maintains a pool of String literal objects to save memory.   This is a behind the scenes process called interning which is outside the scope of this article.

So in the code example, both variables actually point to the same object in memory.

Conclusion

Always use the equals() or equalsIgnoreCase() methods for string equality in Java.   Doing so will reduce the chances of creating subtle bugs in the code that are difficult to detect.