为什么相同的java字符串采用相同的地址?

时间:2012-11-19 08:55:39

标签: java string javac

  

可能重复:
  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分配给同一个对象?或者我在字符串的基础机制中遗漏了什么?

4 个答案:

答案 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中。