5

在测试字符串创建和检查其哈希码时,我发现了一个有趣的案例。

在第一种情况下,我使用复制构造函数创建了字符串:

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));
    }


}

上述代码的输出是:

S1:816115710 S3:478684581

这是预期的输出,因为实习字符串从字符串池中选择引用,而 s1 选择新对象的引用。所以他们的身份哈希码是不同的。

现在,如果我使用 char 数组创建字符串,那么我会看到一些奇怪的行为:

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));
    }

}

上述代码的输出是:

S5:816115710 S6:816115710

这是一个意外的输出。实习字符串和新字符串对象如何具有相同的身份哈希码?

有任何想法吗?

4

1 回答 1

3

在第一种情况下,myTestString文字在您调用之前intern位于池中,而在第二种情况下,您的 String 不是s5直接放入池中。

如果我们逐步浏览您的示例,则会发生以下情况:

  • String s1 = new String("myTestString");=> 使用 String 字面量会myTestString在池中创建一个 String(我们称之为s0),同时还会创建一个新的 String s1,它不在池中。
  • String s3 = s1.intern();=> 检查池中是否存在等效的字符串并找到s0. 现在s3s0引用相同的实例(即是真s3 == s0的,但是s1 != s0)。

在您的第二个示例中:

  • String s5 = new String(c1);创建一个不在池中的新字符串
  • String s6 = s5.intern();检查是否myTestString在池中但找不到它,因此调用会在池中intern创建一个新的 String引用,该引用与s5. 也是如此s6 == s5

最后你可以运行这两个程序来确认我的解释(第二个打印true三遍):

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);
}
于 2013-05-19T09:33:22.917 回答