Why does the following expression evaluate as false
aStr.replace("H", "H") == "Hello"
while this alternate expression evaluates as true?
aStr.replace('H', 'H') == "Hello"
Why does the following expression evaluate as false
aStr.replace("H", "H") == "Hello"
while this alternate expression evaluates as true?
aStr.replace('H', 'H') == "Hello"
Java caches String
literal in String pool, so if there is no change in String
it would take an immutable instance from pool and so that both refers to same instance in memory and thus ==
on reference returns true
So to compare String Object you should use equals()
method / compareTo()
method
Also See
String comparison should be done using .equals()
If the comparison is between String literals, then == comparison may work, because literals are cached in pool and refer to same variable.
equals()
compares values, ==
compares reference.
The String
class's replace(char, char)
method scans looking for a matching character. If it doesn't find one, it returns the host String
instance as is. Naturally, comparing the returned reference to the original reference by way of the ==
operator returns true, as that's testing reference equality, and the two references are one and the same.
If, however, the original string contains an 'H' character—using your example here—then the returned string will not be the same as the original string (even though it will be the same character-by-character); it will be a freshly-allocated instance which would fail the comparison by reference equality (again, the ==
operator). Comparing the returned String
with the original via Object#equals()
would return true, as the two strings are equivalent, but they would be distinct instances that fail to match via reference equality.
By contrast, String#replace(CharSequence, CharSequence)
treats the target string as a regular expression; it uses Matcher#replaceAll()
internally to replace the matches in the target pattern with the supplied replacement sequence.
Now the question comes down to whether or not Matcher#replaceAll()
will return the original string or a freshly-allocated copy even when the pattern doesn't match. By my reading of the code in the Oracle library, if the Matcher
doesn't find the pattern to match, it returns CharSequence#toString()
on the original CharSequence
, which for a String
objects just returns the this
reference unmolested. That leaves me wondering whether you're reporting the true outcome here.
One glaring hole in the question as posed is the original content of the String
referenced by aStr
. You probably meant to show a declaration like
final String aStr = "Hello";
but you didn't. The outcome of both expressions should depend on whether aStr
contains an 'H' character or not. Assuming it does, I expect both expressions to yield false, assuming that no string interning is in play by either of the String#replace()
overloads. We know that the string literals are interned, but the return values we see constructed in the Oracle library's implementation of both String#replace()
methods are freshly allocated and not drawn from the intern pool.
use String.equals () to compare strings.
System.out.println((aStr.replace("H","H").equals("Hello")));
would return true.