218

I know that == has some issues when comparing two Strings. It seems that String.equals() is a better approach. Well, I'm doing JUnit testing and my inclination is to use assertEquals(str1, str2). Is this a reliable way to assert two Strings contain the same content? I would use assertTrue(str1.equals(str2)), but then you don't get the benefit of seeing what the expected and actual values are on failure.

On a related note, does anyone have a link to a page or thread that plainly explains the problems with str1 == str2?

isherwood
  • 58,414
  • 16
  • 114
  • 157
DivideByHero
  • 19,715
  • 24
  • 57
  • 64
  • 1
    If you are unsure, you can read the code, or the Javadoc. BTW if you want to test they are the same object you can use assertSame. – Peter Lawrey Dec 10 '09 at 20:51
  • 2
    If str1 and str2 are null, assertEquals() is true, but assertTrue(str1.equals(str2)) throws an exception. The first example will also print a useful error message such as the contents of str1 and str2, the second does not. – Peter Lawrey Jan 20 '10 at 20:49

7 Answers7

305

You should always use .equals() when comparing Strings in Java.

JUnit calls the .equals() method to determine equality in the method assertEquals(Object o1, Object o2).

So, you are definitely safe using assertEquals(string1, string2). (Because Strings are Objects)

Here is a link to a great Stackoverflow question regarding some of the differences between == and .equals().

Community
  • 1
  • 1
jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • 13
    IIRC assertEquals() succeeds if both strings are null. If this is not what you want then call assertNotNull() as well. – finnw Jul 29 '09 at 18:01
  • 11
    additionally, if you want to test for ==, you can call assertSame() – james Jul 29 '09 at 18:37
  • 9
    I wouldn't say *always*; sometimes reference equality is desired, even for strings. – Karu Aug 14 '14 at 12:33
33

assertEquals uses the equals method for comparison. There is a different assert, assertSame, which uses the == operator.

To understand why == shouldn't be used with strings you need to understand what == does: it does an identity check. That is, a == b checks to see if a and b refer to the same object. It is built into the language, and its behavior cannot be changed by different classes. The equals method, on the other hand, can be overridden by classes. While its default behavior (in the Object class) is to do an identity check using the == operator, many classes, including String, override it to instead do an "equivalence" check. In the case of String, instead of checking if a and b refer to the same object, a.equals(b) checks to see if the objects they refer to are both strings that contain exactly the same characters.

Analogy time: imagine that each String object is a piece of paper with something written on it. Let's say I have two pieces of paper with "Foo" written on them, and another with "Bar" written on it. If I take the first two pieces of paper and use == to compare them it will return false because it's essentially asking "are these the same piece of paper?". It doesn't need to even look at what's written on the paper. The fact that I'm giving it two pieces of paper (rather than the same one twice) means it will return false. If I use equals, however, the equals method will read the two pieces of paper and see that they say the same thing ("Foo"), and so it'll return true.

The bit that gets confusing with Strings is that the Java has a concept of "interning" Strings, and this is (effectively) automatically performed on any string literals in your code. This means that if you have two equivalent string literals in your code (even if they're in different classes) they'll actually both refer to the same String object. This makes the == operator return true more often than one might expect.

Laurence Gonsalves
  • 137,896
  • 35
  • 246
  • 299
  • "That is, a == b checks to see if a and b are the same object." Technically it checks whether a and b REFER to the same object, since a and b are references. Unless I'm very wrong. – bob Jun 03 '15 at 18:37
  • @user1903064 that is correct. Since non-primitive variables can only contain references in Java, it's common to skip the extra level of indirection when talking about them, but I agree that in this case being more explicit is beneficial. I've updated the answer. Thanks for the suggestion! – Laurence Gonsalves Jun 04 '15 at 02:02
9

In a nutshell - you can have two String objects that contain the same characters but are different objects (in different memory locations). The == operator checks to see that two references are pointing to the same object (memory location), but the equals() method checks if the characters are the same.

Usually you are interested in checking if two Strings contain the same characters, not whether they point to the same memory location.

Ken Liu
  • 22,503
  • 19
  • 75
  • 98
7
public class StringEqualityTest extends TestCase {
    public void testEquality() throws Exception {
        String a = "abcde";
        String b = new String(a);
        assertTrue(a.equals(b));
        assertFalse(a == b);
        assertEquals(a, b);
    }
}
Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
5

The JUnit assertEquals(obj1, obj2) does indeed call obj1.equals(obj2).

There's also assertSame(obj1, obj2) which does obj1 == obj2 (i.e., verifies that obj1 and obj2 are referencing the same instance), which is what you're trying to avoid.

So you're fine.

Jack Leow
  • 21,945
  • 4
  • 50
  • 55
3

Yes, it is used all the time for testing. It is very likely that the testing framework uses .equals() for comparisons such as these.

Below is a link explaining the "string equality mistake". Essentially, strings in Java are objects, and when you compare object equality, typically they are compared based on memory address, and not by content. Because of this, two strings won't occupy the same address, even if their content is identical, so they won't match correctly, even though they look the same when printed.

http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/

Soviut
  • 88,194
  • 49
  • 192
  • 260
0

"The == operator checks to see if two Objects are exactly the same Object."

http://leepoint.net/notes-java/data/strings/12stringcomparison.html

String is an Object in java, so it falls into that category of comparison rules.

jjnguy
  • 136,852
  • 53
  • 295
  • 323