我在使用字符串创建和检查其哈希码进行测试时发现了一个有趣的案例。
在第一种情况下,我使用复制构造函数创建了字符串:
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数组创建String,那么我会看到一些奇怪的行为:
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
这是意外的输出。 interned String和new String对象如何具有相同的identityhashcode? p>
有什么想法吗?
答案 0 :(得分:3)
在第一种情况下,myTestString
字面值在之前调用intern
,而在第二种情况下,它不是你的字符串{{1} }直接放入池中。
如果我们一步一步地查看您的示例,则会发生以下情况:
s5
=>使用String文字在池中创建一个String String s1 = new String("myTestString");
(让我们称之为myTestString
),并且还创建一个新的String s0
,它不在池中。s1
=>检查池中是否存在等效的String并找到String s3 = s1.intern();
。现在s0
和s3
引用相同的实例(即s0
为真,但s3 == s0
)。在你的第二个例子中:
s1 != s0
创建一个新的String,它不在池中String s5 = new String(c1);
检查池中是否有String s6 = s5.intern();
但找不到它,因此对myTestString
的调用会在池中创建一个新的String 引用它引用与intern
相同的字符串。所以s5
是真的。最后你可以运行这两个程序来确认我的解释(第二个打印s6 == s5
三次):
true