可能重复:
String object creation using new and its comparison with intern method
我正在玩Strings以更多地理解它们,我发现了一些我无法解释的事情:
String str1 = "whatever";
String str2 = str1;
String str3 = "whatever";
System.out.println(str1==str2); //prints true...that's normal, they point to the same object
System.out.println(str1==str3); //gives true..how's that possible ?
最后一行是如何实现的?这意味着str1和str3在内存中都具有相同的地址。
这是一个足够聪明的编译器优化来检测两个字符串文字是否相同(“无论什么”)并因此将str1和str3分配给同一个对象?或者我在字符串的基础机制中遗漏了什么?
答案 0 :(得分:7)
因为Java有一个独特的interned实例池,并且该字符串文字存储在此池中。这意味着第一个“what”字符串文字与第三个“what”字面值完全相同。
正如文件所说:
<强>
public String intern()
强>返回。的规范表示 字符串对象。保持最初为空的字符串池 私有地通过String类。
当调用实习方法时,如果池已包含 字符串等于此字符串对象由equals(Object)确定 方法,然后返回池中的字符串。否则,这个 String对象被添加到池中以及对此String的引用 返回对象。
对于任何两个字符串s和t,s.intern()== t.intern() 当且仅当s.equals(t)为真时才为真。
所有文字字符串和字符串值常量表达式都是 实习。字符串文字在Java语言的§3.10.5中定义 规格
返回:与此字符串具有相同内容的字符串,但是 保证来自一串独特的字符串。
答案 1 :(得分:5)
http://www.xyzws.com/Javafaq/what-is-string-literal-pool/3
正如帖子所说:
与所有对象分配一样,字符串分配在时间和内存方面都证明是昂贵的。 JVM在实例化字符串文字时执行一些技巧,以提高性能并减少内存开销。为了减少在JVM中创建的String对象的数量,String类保留了一个字符串池。每次代码创建字符串文字时,JVM首先检查字符串文字池。如果池中已存在该字符串,则返回对池化实例的引用。如果池中不存在该字符串,则新的String对象将实例化,然后放入池中。
答案 2 :(得分:2)
如果你这样做:
String str1 = new String("BlaBla"); //In the heap!
String str2 = new String("BlaBla"); //In the heap!
然后您通过String
运算符(和构造函数)明确创建new
对象。
在这种情况下,您将使每个对象指向不同的存储位置。
但如果你这样做:
String str1 = "BlaBla";
String str2 = "BlaBla";
那么你就是隐含的构造。 如果两个字符串文字具有相同的值,则它们共享相同的存储空间,这是因为Java保留了相同字符串的存储空间! (具有相同值的字符串)
答案 3 :(得分:1)
javac
编译器组合了在给定类文件中相同的字符串文字。
但是在运行时,使用与String.intern()相同的方法组合字符串文字。这意味着甚至在不同应用程序中的不同类中使用字符串(在使用相同对象的同一JVM中。