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

2022-09-01 20:33:03

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

我有两个字符串定义为

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

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


答案 1

组合相同字符串的过程称为“实习”,并且已经由许多语言编译器完成了很多年,但并非总是如此。问题的答案,特别是通过@GennadyVanin - 新西伯利亚扩展,取决于语言和编译器实现。对于 Java,根据 Java 语言规范的要求,所有常量字符串都将被暂存。但这只是常量字符串表达式,并且仅当它们同时编译时。如果有两个 Java 字符串在时间和空间上充分分离(例如,编译成单独的 JAR 文件),它们将不是同一个对象。类似地,动态创建的Java字符串(例如,各种方法的输出)也不会被暂存,除非该方法通过 专门请求它。是的,所有使用暂存字符串都将共享相同的内存位置 - 这是字符串首先被暂留的原因的很大一部分。toString()String.intern()

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


答案 2
String s1="Java";
String s2="Java";
My question is whether these two references point to the same memory location  

愚蠢地引用 Java 语言规范的 §3.10.5

字符串文本是对类 String (§4.3.1, §4.3.3 的实例的引用。

此外,字符串文本始终引用类 String 的同一实例。这是因为字符串文本 (或者更一般地说,作为常量表达式的值的字符串 (§15.28) ) 被“暂存”,以便使用 String.intern 方法共享唯一实例。

并阅读那里的代码示例注释:

此示例说明了六点:

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

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

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

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

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

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