4

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"
seh
  • 14,999
  • 2
  • 48
  • 58
  • 3
    Use `.equals()` to compare `String`s. – João Silva Sep 28 '12 at 19:11
  • Does `aStr` contain an 'H' character or not? – seh Sep 28 '12 at 19:16
  • 1
    *Everyone* missed the root question, which was *not* a duplicate! In this specific case, the implementation for `replace(char, char)` starts with `if (oldChar != newChar) { ... } return this;` So your simple test returned the same instance... which is why the `==` succeeded. As has already been mentioned, use `equals` to compare objects for equivalence, rather than the `==` which checks for *same* object instance. – Richard Sitze Sep 28 '12 at 19:21
  • 2
    I was in the middle of writing a lengthy answer to the real question, as Richard notes, but even then, if `aStr` does *not* contain an `H` character, then ever the first call to `String#replace(CharSequence, CharSequence)` should have also returned true. It does with Oracle's JDK. Study how `Matcher#replaceAll()` works to see why. – seh Sep 28 '12 at 19:46
  • I re-opened this because I think a few folks have missed the actual question. – Kev Oct 01 '12 at 00:24

4 Answers4

4

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

Community
  • 1
  • 1
jmj
  • 237,923
  • 42
  • 401
  • 438
2

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.

kosa
  • 65,990
  • 13
  • 130
  • 167
2

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.

seh
  • 14,999
  • 2
  • 48
  • 58
0

use String.equals () to compare strings.

        System.out.println((aStr.replace("H","H").equals("Hello")));

would return true.

PermGenError
  • 45,977
  • 8
  • 87
  • 106