使用JDK1.8
//create string s1
String s1 = new String("1")+new String("1");
//native method, put s1 into string constant pool
s1.intern();
//create variable s2
String s2 = "11";
System.out.println(s1 == s2);
在此代码中将输出true,但是如果用以下代码替换第一行
String s1 = new String("11")+new String("");
它将输出false
现在我的疑问是:
当第一个代码运行时,堆和池中发生了什么?和代码intern
最好向我描述每一步在堆和池之间如何变化,谢谢
答案 0 :(得分:1)
您应该仔细阅读the documentation of s1.intern()
:
返回字符串对象的规范表示。
…
调用intern方法时,如果池中已经包含一个由String
方法确定的与此equals(Object)
对象相等的字符串,则返回池中的字符串。否则,将此String
对象添加到池中,并返回对此String
对象的引用。
由于合同是关于方法将返回的内容,因此您不应忽略方法调用的返回值。
您关于s1.intern();
将“将s1放入字符串常量池”的假设是错误的。该方法将返回包含在常量池中的字符串,如果没有相同内容的字符串,则该可能是现在已添加到池中的相同字符串以前。
因此,在您的第一个测试中,您展示了添加到池中的字符串的特定于实现的行为,因为以前没有字符串具有相同的内容。
相反,在第二个测试中,可以保证不会将字符串添加到池中。随着文档的继续:
所有文字字符串和字符串值常量表达式均已插入。字符串文字是在 Java™语言规范的第3.10.5节中定义的。
您已经通过将字符串引用与为"11"
调用后出现的文字intern()
创建的引用进行比较来利用此行为。但是,当您的代码以String s1 = new String("11")+new String("");
开头时,您在调用之前 有一个字符串文字"11"
,该字符串将自动添加到池中。表达式new String("11")+new String("")
创建一个新的String
实例,该实例与字符串文字不同,并且没有添加到池中,因为已经有一个内容相同的字符串。
当我们实际使用返回值时,这很容易证明:
String s1 = new String("11")+new String("");
String shouldBeInPool = s1.intern();
String s2 = "11";
System.out.println(shouldBeInPool == s2);
打印true
。
请注意,您的第一个示例
String s1 = new String("1")+new String("1");
s1.intern();
String s2 = "11";
System.out.println(s1 == s2);
将在较旧的JDK上打印false
,例如Sun的JDK 6。
答案 1 :(得分:0)
无论何时创建字符串对象,都会创建两个对象,即一个在堆区域中,一个在字符串常量池中,并且字符串对象引用始终指向堆区域对象。因此将在堆区域中创建一个新的String(“ 11”)对象,并且s1引用指向堆。您可以访问的详细信息:https://www.geeksforgeeks.org/interning-of-string/,希望您喜欢!