如果池内存已经有一个具有相似内容的对象,那么如果我们尝试使用不同的引用变量创建相同的对象,那么只创建一个新的引用变量,NO NEW OBJECT IS CREATED.eg;
String s7="1";
String s8 ="1";
System.out.print(s7==s8); //True
这里只创建了一个对象。 但是在下面的例子中
public class JavaApplication1 {
public static void main(String[] args) {
String s1 = "1", s2 = "2", s4 = s1 + s2, s5 = "12";
final String s3 = s1 + s2;
s1 += s2;
System.out.print((s1 == s3) + "" + (s1 == s5) + "" + "" (s3 == s5));
}
}
输出为false false false 甚至将s3声明为最终表达式!为什么?
答案 0 :(得分:1)
If pool memory already has an object with similar content, then if we try to create the same object with different reference variable then only a new reference variable is created, NO NEW OBJECT IS CREATED.eg;
在一般情况下,实际上并非如此。您所描述的内容称为String interning
。 interned
字符串始终是引用 - 等于具有相同内容的任何其他实习字符串 - 这基本上是intern
的保证。 (来自String.intern
上的docs:接下来,对于任何两个字符串s和t,当且仅当s.equals时,s.intern()== t.intern()为真(t)是真的。)。如果我要从一个常量字节数组创建2个字符串,那么即使它们共享内容,它们也会是不同的对象。
JLS进一步指明:
此外,字符串文字始终引用类String的相同实例。这是因为字符串文字 - 或者更常见的是作为常量表达式(第15.28节)的值的字符串 - 被“实例化”以便使用String.intern方法共享唯一实例。
因此,为什么你得到字符串文字的相等性,以及任何值为[a]常量表达式的东西。
那么,这个常量表达式是什么?好吧,根据JLS,这些是文字,简单名称(§6.5.6.1)引用常量变量,各种非String内容和+
表达式,但是只要+
的两个操作数都是constant expressions
( String对象是新创建的(§12.5),除非表达式是常量表达式(§15.28)。) 。所以这意味着,除非+
的两个侧的字符串都是文字,否则最终字符串的值为常量表达式或满足其他条件之一(就像来自原始常量的强制转换),将创建一个新对象。
答案 1 :(得分:1)
这是因为
1)由常量表达式计算的字符串(第15.28节)在编译时计算,然后视为文字。
2)在运行时通过串联计算的字符串是新创建的,因此是不同的。
以下是一个例子:
String s7 = "77";
String s8 = "77";
String s10 = "7";
String s11 = "7";
String s9 = s10+s11;
String s12 = "7"+"7";
//printing the address
System.out.println(System.identityHashCode(s7));
System.out.println(System.identityHashCode(s8));
System.out.println(System.identityHashCode(s9));
System.out.println(System.identityHashCode(s12));
System.out.println(s7==s9);
System.out.println(s7==s12);
<强> 输出: 强>
705927765
705927765
366712642 ---> address is different
705927765
false
true
虽然我刚才也经历过这个问题。但这是我的假设:
除了String s9 = s10+s11;
之外的所有文字都是在编译时计算的。这就是为什么我们得到不同的地址。
关注String literals javadoc了解详情。