5

I found an interesting case while testing with string creation and checking their hashcode.

In first case i created string using copy constructor:

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {

        String s1 = new String("myTestString");

        String s3 = s1.intern();

        System.out.println("S1: " + System.identityHashCode(s1) + "  S3:"
                + System.identityHashCode(s3));
    }


}

Output of above code is:

S1: 816115710 S3:478684581

This is expected output as interned string picks the reference from String pool whereas s1 picks reference of new object. So their identity hash code is different.

Now if i create String using char array then i see some strange behavior:

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {

        char[] c1 = { 'm', 'y', 'T', 'e', 's', 't', 'S', 't', 'r', 'i', 'n',
                'g' };

        String s5 = new String(c1);

        String s6 = s5.intern();

        System.out.println("S5: " + System.identityHashCode(s5) + "  S6:"
                + System.identityHashCode(s6));
    }

}

Output of above code is:

S5: 816115710 S6:816115710

This is an unexpected output. How can interned String and new String object have same identityhashcode??

Any ideas?

6
  • Take a look at stackoverflow.com/questions/1063068/… Commented May 19, 2013 at 9:30
  • @IgorS.: How is it linked to my question? Commented May 19, 2013 at 9:31
  • 1
    "Multiple objects can have the same identity hash code. That is the nature of hash codes." Commented May 19, 2013 at 9:34
  • @IgorS.: Yes they can have only in certain scenarios. In above scenario they should not have. Commented May 19, 2013 at 9:35
  • It should. To keep memory usage low - VM clearly use lazy loading, because you didn't do anything with strings it pointing to the same memory address. First case is probably different, because of characters encoding or/and string end character. Commented May 19, 2013 at 9:41

1 Answer 1

3

In the first case, the myTestString literal is on the pool before you call intern, whereas in the second case it is not so your String s5 is put in the pool directly.

If we go through your examples step by step, this is what happens:

  • String s1 = new String("myTestString"); => the use of a String literal creates a String myTestString in the pool (let's call it s0), and a new String s1 is also created, which is not in the pool.
  • String s3 = s1.intern(); => checks if there is an equivalent String in the pool and finds s0. Now s3 and s0 refer to the same instance (i.e. s3 == s0 is true, but s1 != s0).

In your second example:

  • String s5 = new String(c1); creates a new String, which is not in the pool
  • String s6 = s5.intern(); checks if myTestString is in the pool but can't find it, so the call to intern creates a new String reference in the pool that refers to the same String as s5. So s6 == s5 is true.

Finally you can run these two programs to confirm my explanation (the second one prints true three times):

public static void main(String[] args) {
    String s1 = new String("myTestString");
    String s3 = s1.intern();
    System.out.println("myTestString" == s1);
    System.out.println(s3 == s1);
    System.out.println("myTestString" == s3);
}

public static void main(String[] args) {
    String s1 = new String(new char[] {'m', 'y', 'T', 'e', 's', 't', 'S', 't', 'r', 'i', 'n', 'g'});
    String s3 = s1.intern();
    System.out.println("myTestString" == s3);
    System.out.println("myTestString" == s1);
    System.out.println(s3 == s1);
}
Sign up to request clarification or add additional context in comments.

8 Comments

Why would s5 be put into pool directly? I am using new operator to create it.
It is put in the pool when you call intern because that specific string was not already in the pool. How you created the string is irrelevant in that case.
same should also apply to s1, s3 then. Why is that different?
@loki I have added more details. The difference is that in your first example there is a String literal which goes to the pool before your program runs.
+1 good point, didn't thought about explaining the "expected result" ;)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.