Experimenting with String creation
我在测试字符串创建并检查其哈希码时发现了一个有趣的案例。
在第一种情况下,我使用复制构造函数创建了字符串:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
上面代码的输出是:
S1: 816115710 S3:478684581
这是预期的输出,因为实习字符串从字符串池中选择引用,而 s1 选择新对象的引用。所以他们的身份哈希码是不同的。
现在,如果我使用 char 数组创建字符串,那么我会看到一些奇怪的行为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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
这是一个意外的输出。实习字符串和新字符串对象如何具有相同的身份哈希码??
有什么想法吗?
在第一种情况下,
如果我们逐步查看您的示例,会发生以下情况:
-
String s1 = new String("myTestString"); => 使用字符串字面量在池中创建了一个字符串myTestString (我们称之为s0 ),同时还创建了一个新的字符串s1 ,它不在池中。 -
String s3 = s1.intern(); => 检查池中是否存在等效字符串并找到s0 。现在s3 和s0 引用同一个实例(即s3 == s0 为真,但s1 != s0 )。
在你的第二个例子中:
-
String s5 = new String(c1); 创建一个新的字符串,它不在池中 -
String s6 = s5.intern(); 检查myTestString 是否在池中但找不到它,因此对intern 的调用会在池中创建一个新的字符串引用,该引用与s5 引用相同的字符串。所以s6 == s5 是真的。
最后你可以运行这两个程序来确认我的解释(第二个打印
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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); } |