13

Possible Duplicate:
String comparison and String interning in Java

I try to run the following code in java:

if("hello".trim() == "hello".trim())
   System.out.println("Equal");
else
   System.out.println("Not Equal");

and it prints Equal. I understand in this case both strings have same reference. But When I try the same by just adding a space in both strings, it prints "Not Equal".

if("hello ".trim() == "hello ".trim())
   System.out.println("Equal");
else
  System.out.println("Not Equal");

Can anyone explain why I am getting "Not Equal"...?

Community
  • 1
  • 1
user1709584
  • 139
  • 2
  • 2
    see also http://stackoverflow.com/questions/3885753/string-comparison-and-string-interning-in-java –  Sep 30 '12 at 10:00
  • 2
    do not use == to compare objects unless you want to check for instance identity, equals is what you want. – josefx Sep 30 '12 at 10:59
  • What I do not understand is how he gets "Equal" on the first one. Those are two different references. Right? – mrres1 Sep 30 '12 at 16:15
  • For the record, it was inappropriate to close this question as yet another instance of equals vs. == on strings. OP is fully aware of the distinction and the question is about the surprising difference in the behavior of `trim` in two apparently similar scenarios. – Marko Topolnik Oct 01 '12 at 06:28

4 Answers4

16

Just check out the implementation of trim and it will be clear to you. If trim determines that the string has no leading/trailing whitespace, it returns the same string—that's your first case. In the second case a new string is created, so you have two equal String instances, each with its own identity. And, as I think you are aware, the operator == compares references and not objects, so it doesn't care whether the two instances represent equal strings or not.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
6

This behaviour is described in the JavaDoc of trim() (bold mine):

A copy of this string with leading and trailing white space removed, or this string if it has no leading or trailing white space.

It's pretty clear from the implementation as well:

public String trim() {
    //...
    return ((st > 0) || (len < count)) ? substring(st, len) : this;
}

If some leading or trailing whitespaces were discovered, substring() is called returning new String. this is returned otherwise.

Interesting fact: in both cases (if this is returned and when substring() is called) returned objects point to the same, original char[] array. Only the wrapping String object changes and the array indexes selecting a subset of that array.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
3
if("hello".trim() == "hello".trim())

Here your string is not actually modified.. whereas, in the second case: -

if("hello ".trim() == "hello ".trim())

You are modifying the string.. And both the strings create different objects..

Although, if you try to compare them using equals() method, you will get the result as desired.. As equals() method compares the content of two strings, whereas == compares the reference..

So, when two different objects of strings with same content are compared using ==, you are actually comparing the reference of those strings, which are different..

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • To be absolutely crystal clear, this answer should point out that `==` compares references, and so tests object *identity*, whereas `equals` compares values (through a polymorphic method), and so tests *equality*. Identity vs equality is an important distinction. – Tom Anderson Sep 30 '12 at 10:03
  • @TomAnderson.. Yeah edited to add some more information.. – Rohit Jain Sep 30 '12 at 10:05
  • @TomAnderson Strictly put, the value of `String s` is a reference, so what == compares are indeed variable values. It is `equals` that **doesn't** simply compare values, but the objects referenced by those values. – Marko Topolnik Sep 30 '12 at 10:07
  • How so? How is the second case different? – techfoobar Sep 30 '12 at 10:08
  • @MarkoTopolnik.. True :) – Rohit Jain Sep 30 '12 at 10:08
  • @MarkoTopolnik: True. What i meant, and should have said more clearly, is that `==` compares the values of two expressions, whereas `equals` compares the values in the fields of the objects pointed to by two expressions. Although, of course, since `equals` is a method, it can do anything it likes (including `return Math.random() > 0.5;`); what is *should* do is compare the contents of the objects (probably - at least for value objects). – Tom Anderson Sep 30 '12 at 10:10
1

From the documentation - Trim:

"If this String object represents an empty character sequence, or the first and last characters of character sequence represented by this String object both have codes greater than '\u0020' (the space character), then a reference to this String object is returned."

(in the case of your first example, you get the same reference)

"Otherwise, let k be the index of the first character in the string whose code is greater than '\u0020', and let m be the index of the last character in the string whose code is greater than '\u0020'. A new String object is created, representing the substring of this string that begins with the character at index k and ends with the character at index m-that is, the result of this.substring(k, m+1)."

(so, two new strings are created, the decision returns false since the two objects in memory are different)

For future reference, you can do this: if ("hello ".trim().equals("hello ".trim())) to check if the contents of the two strings are equal.

mfjones
  • 739
  • 4
  • 16