Last week, we had the author of TDD for a Shopping Website LiveProject. Friday at 11am Ranch time, Steven Solomon will be hosting a live TDD session just for us. See for the agenda and registration link
WHEN ARE TWO STRINGS EQUAL? Strings are treated differently by Java developers than other first class objects. You can initialize a new String using new:
String string = new String("hello"); //not recommended
You can also use the following syntax to accomplish almost the same thing:
String string = "hello";
This tip addresses the question "when are two Strings equal?" Because they are objects, you can always compare the values of two Strings using the equals() method. If s1 and s2 are two Strings with the same value, then s1.equals(s2) is true. The tricky part comes when you try to use == to compare s1 and s2. In this tip you will see when s1 == s2 should return true.
To start with, create two objects of type Double, two primitives of type double, and two objects of type String. Use the s1 = "hello" syntax for initializing the Strings.
When your run Equals, you get the following results:
For Double objects both 7.2 object1 == object2 is false object1.equals(object2) is true For double primitives both 7.2 prim1 == prim2 is true For Strings both 7.2 string1 == string2 is true string1.equals(string2) is true
As you would expect, object1.equals(object2) is true because they have the same value but object1 == object2 is false because they are different objects. Also, prim1 == prim2 is true because they have the same value (note that you cannot use equals() to compare two primitives). For the objects string1 and string 2, string1.equals(string2) is true because their values are the same. Perhaps it is a surprise that string1 == string2 is true. The Java Language Specification explains that "Literal strings within the same class in the same package represent references to the same String object."
The Language Specification explains that "String literals - or, more generally, strings that are the values of constant expressions - are 'interned' so as to share unique instances using the method String.intern."
On the surface, the next example seems to highlight the differences between initializing a String as you would initialize an object, and initializing a String as you would initialize a primitive. It actually demonstrates the difference between obtaining a String by using a String literal directly, and by calling a String constructor.
Run NewEquals, and you will see these results:
For new Strings s1 and s2 s1 == s2 is false s1.equals(s2) is true For Strings s1 and s3 s1 == s3 is false s1.equals(s3) is true
All three Strings are created with the same value, so equals() returns true for both comparisons. However, s1 and s2 are different objects. Despite being constructed with the same value, they are as different as the two Double objects were in the first example. This is why s1 == s2 is false. Similarly, s1 == s3 is also false.
You probably wouldn't be surprised by this result if it were not for the first example (Equals) where the two Strings returned true when compared with the == operator. It seems that these objects have the behavior expected of objects. The Equals example showed you that there is a pool for Strings. Multiple String variables can refer to the same String object. If they are set to equal string literals, they are guaranteed to do so.
The Language Specification guarantees that calling new will create a new object. That object has never been passed to String.intern. However, the value of a String literal is a String that has been passed String.intern, so it is different. The Language Specification does say that you can force a String into the common String pool using the intern() method, as shown in the following example:
Here are the results of running NewInternString:
For new Strings s1 and s2 s1 == s2 is false s1.equals(s2) is true For Strings s1 and s3 s1 == s3 is true s1.equals(s3) is true
You can see that again the values are being reported as equal. That's because the equals() method returns true in both cases. After you force s1 into the constants pool you find that s1 == s3 is true. However, s2 is still not in the constants pool, so s1 == s2 is false.
In this tip you saw that the only safe way to test that Strings have the same value is with the equals() method. If you work with Strings that have the same value, then it might be worth interning them into the constants pool. That way you can make a quicker check using the == operator. In any case, you can see that you have to be careful before deciding to use == to check equivalence.
For more information on String comparisons see section 9.2 "String Comparisons" in The Java Programming Language Third Edition by Arnold, Gosling, and Holmes.