Java 具有相同内容的两个字符串是否存储在同一内存位置?

Java 具有相同内容的两个字符串是否存储在同一内存位置?,java,string,memory-management,Java,String,Memory Management,这是我在采访中得到的一个问题 我有两个字符串定义为 String s1="Java"; String s2="Java"; 我的问题是这两个引用是否指向同一个内存位置。通常,当我们创建相同的字符串(没有new关键字)时,内容是否只存储在内存中一次,并且具有相同内容的所有字符串对象只引用相同的位置,而没有冗余地存储字符串“Java”?s1和s2的哈希代码相同。但哈希代码是否直接依赖于对象的内存位置 当编译器优化字符串文本时,它会发现s1和s2都有相同的值,因此您只需要一个字符串对象。它是安全的,

这是我在采访中得到的一个问题

我有两个字符串定义为

String s1="Java";
String s2="Java";

我的问题是这两个引用是否指向同一个内存位置。通常,当我们创建相同的字符串(没有new关键字)时,内容是否只存储在内存中一次,并且具有相同内容的所有字符串对象只引用相同的位置,而没有冗余地存储字符串“Java”?s1和s2的哈希代码相同。但哈希代码是否直接依赖于对象的内存位置

当编译器优化字符串文本时,它会发现s1和s2都有相同的值,因此您只需要一个字符串对象。它是安全的,因为字符串在Java中是不可变的

String s1="Java";
String s2="Java";
System.out.println(s1== s2);
这将给出结果
true
,因为
s1
s2
指向同一个对象

字符串池是一种机制,所有已定义的字符串都存储在某个“池”中,在创建新的字符串对象之前,编译器会检查此类字符串是否已定义

String s1="Java";
String s2="Java"; 
它们是否指向相同的内存位置

我最初说“不”,但在上面的例子中,请参阅下面提到的StringPool答案,它实际上是“是”

“当我们创建相同的字符串(没有new关键字)时 内容只存储在内存中一次,所有字符串对象都存储在内存中 使用相同的内容只需参考相同的位置”

…可以看到问题的详细答案

“s1和s2的散列码是相同的。但是散列码是相关的吗?” 直接在对象的内存位置上?”

否哈希代码取决于字符串的内容,例如

第一个例子

String s1 = "FirstString";
String s2 = "FirstString";

 if(s1 == s2) {
   //This condition matched true because java don't make separate object for these two string. Both strings point to same reference.
 }
第二个例子

String s1= "FirstString";
String s2 = new String("FirstString");

if(s1.equals(s2)) {
  //This condition true because same content.
}

if(s1 == s2) {
  //This condition will be false because in this java allocate separate reference for both of them
}
结论:Java检查字符串是否存在。如果我们使用“新建”创建第二个字符串的对象并具有不同的内容,则其将创建对象并分配不同的引用;如果我们不使用“新建”创建对象并具有相同的内容,则其将分配与第一个字符串包含的相同引用。

添加到其他字符串: new关键字always强制创建新对象。 如果您声明如下:

String s1 = "some";
String s2 = "some";
然后使用字符串池机制,s1和s2都将引用值为“some”的同一个字符串对象

String str1 = new String("BlaBla");  //In the heap!
String str2 = new String("BlaBla");  //In the heap!
然后通过
new
操作符(和构造函数)显式创建
String
对象。 在这种情况下,每个对象都指向不同的存储位置

但如果你有:

String str1 = "BlaBla";        
String str2 = "BlaBla";
然后你就得到了隐式构造。 如果两个字符串文本具有相同的值,则它们共享相同的存储空间,这是因为Java保存了相同字符串的存储空间!(具有相同值的字符串)


两者都指向同一对象。更详细地说,

组合相同字符串的过程被称为“”,许多语言编译器多年来一直在这样做,但并不总是这样。这个问题的答案,特别是@GennadyVanin--Novosibirsk的扩展,取决于语言和编译器实现。对于Java,所有常量字符串都是内部的,这是。但这只是常量字符串表达式,而且只有在同时编译它们时才会出现。如果您有两个在时间和空间上充分分离的Java字符串(例如,编译成单独的JAR文件),那么它们将不是同一个对象。类似地,动态创建的Java字符串(例如,各种
toString()
方法的输出)不会被插入,除非该方法通过
String.intern()
专门请求它。是的,所有使用一个内联字符串的用户都会共享相同的内存位置——这就是为什么字符串首先被内联的一个重要原因

至于其他语言,这是一个更大的问题,但有了这些答案中的所有信息,我相信你可以在网上研究它。只需说,在如何做到这一点上没有普遍的一致意见

String s1="Java";
String s2="Java";
My question is whether these two references point to the same memory location  
愚蠢的引用:

字符串文字是对类字符串实例的引用 (, ).

此外,字符串文字总是引用类的同一实例 一串这是因为字符串文字,或者更一般地说,字符串 这是常量表达式()的值 “interned”以便使用该方法共享唯一实例 实习医生

并阅读注释以编写示例:

这个例子说明了六点:

  • 同一包(§7)中同一类(§8)中的文字字符串表示对同一字符串对象(§4.3.1)的引用

  • 同一包中不同类中的文字字符串表示对同一字符串对象的引用

  • 不同包中不同类中的文本字符串同样表示对同一字符串对象的引用

  • 由常量表达式(§15.28)计算的字符串在编译时计算,然后将其视为文本

  • 在运行时通过连接计算的字符串是新创建的,因此是不同的

  • 显式插入计算字符串的结果是与任何具有相同内容的预先存在的文本字符串相同的字符串

对, Andrew Hare在这个链接中回答了堆栈溢出问题

基本上,string intern池允许运行时通过在池中保留不可变字符串来节省内存,以便应用程序的各个区域可以重用公共字符串的实例,而不是创建多个实例


错。您可以使用StringBuilder创建字符串实例,如果您创建的字符串已在其他地方用作文本,它将不会!!!不能是相同的字符串,也不能是相同的内存位置。这就是为什么所有字符串比较都必须使用.equals来完成。字符串是引用类型。Onl
String s1="Java";
String s2="Java";
My question is whether these two references point to the same memory location