TheLostMind
TheLostMind

Reputation: 36304

Why does "==" sometimes work with String.trim?

I have the following code

public static void main(String... args) {

    String s = "abc";
    System.out.println(s.hashCode());
    String s1 = " abc ";
    System.out.println(s1.hashCode());
    String s2 = s.trim();
    System.out.println(s2.hashCode());
    String s3 = s1.trim();
    System.out.println(s3.hashCode());
    System.out.println();
    System.out.println(s == s1);
    System.out.println(s == s2);
    System.out.println(s == s3);
}

OP:

96354
32539678
96354
96354

false   -- Correct
true    -- This means s and s2 are references to the same String object "abc" .
false   -- s3=s1.trim()... which means s3="abc" yet s==s3 fails.. If the above conditon were to be considered (s==s2 is true..) , this should also be true.. 

Why am i getting "false" when i check s==s3 ?..

Upvotes: 5

Views: 275

Answers (5)

Steven
Steven

Reputation: 139

The Java 7 source code for java.lang.String.trim() (from the installed JDK) is:

public String trim() {
    int len = value.length;
    int st = 0;
    char[] val = value;    /* avoid getfield opcode */

    while ((st < len) && (val[st] <= ' ')) {
        st++;
    }
    while ((st < len) && (val[len - 1] <= ' ')) {
        len--;
    }
    return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}

The return statement states that if there is no change to the String being trimmed, then this is returned, hence s == s2:

String s = "abc";
String s2 = s.trim();
System.out.println(s == s2); // is true

When the String being trimmed needs to be trimmed, java.lang.String.substring() is called. The source code for substring() in Java 7 is:

public String substring(int beginIndex, int endIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > value.length) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    int subLen = endIndex - beginIndex;
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    return ((beginIndex == 0) && (endIndex == value.length)) ? this
            : new String(value, beginIndex, subLen);
}

When the String being trimmed has to be trimmed, then substring() returns a new String:

new String(value, beginIndex, subLen)

This is why s != s3:

String s = "abc";
String s1 = " abc ";
String s3 = s1.trim();
System.out.println(s == s3); // is false

Source code for this answer is available on GitHub here.

Upvotes: 1

griffon vulture
griffon vulture

Reputation: 6774

see in documentation - http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#trim() -

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

when the string is staying the same it returns the string given itself.

Upvotes: 1

Deepak
Deepak

Reputation: 2895

becuase s1.trim() will return a new instance. Strings are immutable so every time a function applied on Strings then a new instance will be returned and You are using == which compares the instance equality

Edit: As suggested By Chris Hayes and R.J.

trim is smart and returns this if there's no whitespace to trim. So in second case you have ' abc ' white spaces so in this case it is not returning this but a new instance of string.

source code of trim method

Upvotes: 5

denis.solonenko
denis.solonenko

Reputation: 11775

If you take a look at String.trim you'll see that it eventually calls String.substring which in turn returns new String(...) if the string is getting actually trimmed. That's why == fails.

Upvotes: 2

Aniket Thakur
Aniket Thakur

Reputation: 68945

public String trim() {
    int len = value.length;
    int st = 0;
    char[] val = value;    /* avoid getfield opcode */

    while ((st < len) && (val[st] <= ' ')) {
        st++;
    }
    while ((st < len) && (val[len - 1] <= ' ')) {
        len--;
    }
    return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}

As you can see in your case(System.out.println(s == s2);) this is returned which is pointing to same reference which is why you get true.

Upvotes: 2

Related Questions