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

Res*_*esh 18 java string memory-management

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

我有两个字符串定义为

String s1="Java";
String s2="Java";
Run Code Online (Sandbox Code Playgroud)

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

Ros*_*son 23

组合相同字符串的过程称为" 实习 ",并且已经被许多语言编译器多年来完成,但并非总是如此.这个问题的答案,特别是由@ GennadyVanin - Novosibirsk扩展,取决于语言和编译器的实现.对于Java,根据Java语言规范的要求,所有常量字符串都是实例化的.但这只是常量字符串表达式,并且只有在它们同时编译时才会出现.如果您有两个在时间和空间上充分分开的Java字符串(例如,编译成单独的JAR文件),它们将不是同一个对象.类似地,除非方法通过具体请求,否则将不会实现动态创建的Java字符串(例如,各种toString()方法的输出)String.intern().是的,所有使用的实习字符串将共享相同的内存位置 - 这是为什么字符串首先被实习的主要原因.

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

  • 答案不正确.编译时汇集的所有字符串也会在运行时由类加载器轮询,无论它们来自哪个类或JAR. (2认同)

Gen*_*нин 7

String s1="Java";
String s2="Java";
My question is whether these two references point to the same memory location  
Run Code Online (Sandbox Code Playgroud)

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

字符串文字是类字符串(的实例的引用第4.3.1节,§4.3.3).

此外,字符串文字始终引用类String的相同实例.这是因为字符串文字 - 或者更常见的是作为常量表达式(第15.28节)的值的字符串- 被"实例化"以便使用String.intern方法共享唯一实例.

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

这个例子说明了六点:

  • 同一个包(第7节)中同一个类(第8节)中的文字字符串表示对同一个String对象的引用(第4.3.1节).

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

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

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

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

  • 显式实现计算字符串的结果与具有相同内容的任何预先存在的文字字符串的字符串相同.


Ach*_*Jha 5

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

String s1="Java";
String s2="Java";
System.out.println(s1== s2);
Run Code Online (Sandbox Code Playgroud)

这给出了结果,true因为s1s2指向同一个对象.

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