Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Experimenting with String creation

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?

like image 740
Lokesh Avatar asked Oct 21 '22 09:10

Lokesh


1 Answers

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);
}
like image 101
assylias Avatar answered Oct 27 '22 11:10

assylias