java 两个内容相同的字符串会存储在同一个内存位置吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15805578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 20:55:30  来源:igfitidea点击:

will two strings with same content be stored in the same memory location?

javastringmemory-management

提问by Reshma Ratheesh

This is a question that I got in an interview.

这是我在面试中遇到的一个问题。

I've two strings defined as

我有两个字符串定义为

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

My question is whether these two references point to the same memory location. In general, when we create identical strings (without new keyword), does the content get stored in the memory only once and all the String objects with the same content just refer to the same location, without storing the string "Java" redundantly ? The hash codes of s1 and s2 are the same. But are hashcodes dependent directly on memory location of the object?

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

回答by Ross Patterson

The process of combining identical strings is called "interning", and has been done for many years by lots of language compilers, but not always. The answer to the question, especially as expanded by @GennadyVanin--Novosibirsk, depends on the language and the compiler implementation. For Java, all constant strings are interned, as required by the Java Language Specification. But that's only constant string expressions, and only when they're compiled at the same time. If you have two Java strings sufficiently separated in time and space (e.g., compiled into separate JAR files), they will not be the same object. Similarly, dynamically created Java strings (e.g., the output of various toString()methods) won't be interned unless the method specifically requests it via String.intern(). And yes, all uses of an interned string will share the same memory locations - that's a big part of why strings are interned in the first place.

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

As to other languages, that's a bigger question, but with all the information in these answers, I'm sure you can research it on the web. Suffice it to say that there is no universal agreement on how this ought to be done.

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

回答by Gennady Vanin Геннадий Ванин

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

Dumb citing §3.10.5 of Java Language Specification:

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

A string literal is a reference to an instance of class String (§4.3.1, §4.3.3).

Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.

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

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

And read the comments to code example there:

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

This example illustrates six points:

  • Literal strings within the same class (§8) in the same package (§7) represent references to the same String object (§4.3.1).

  • Literal strings within different classes in the same package represent references to the same String object.

  • Literal strings within different classes in different packages likewise represent references to the same String object.

  • Strings computed by constant expressions (§15.28) are computed at compile time and then treated as if they were literals.

  • Strings computed by concatenation at run time are newly created and therefore distinct.

  • The result of explicitly interning a computed string is the same string as any pre-existing literal string with the same contents.

这个例子说明了六点:

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

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

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

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

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

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

回答by Achintya Jha

When compiler optimizes your string literals, it sees that both s1 and s2 have same value and thus you need only one string object. It's safe because String is immutable in Java.

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

String s1="Java";
String s2="Java";
System.out.println(s1== s2);

This gives result truebecause s1and s2points to the same object.

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

String Poolis the mechanism that all already defined string are stored in some 'pool' and before creating new String object compiler checks if such string is already defined.

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

回答by Ajay S

Example.

例子。

First example

第一个例子

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.
 }

Second example

第二个例子

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
}

Conclusion: Java check whether string exist or not. If we create the object of second string using new and have different content then its creates object and assign different reference and In case of If we don't create the object using new and have same content then its assign the same reference as first string contain.

结论:Java 检查字符串是否存在。如果我们使用 new 创建第二个字符串的对象并具有不同的内容,那么它会创建对象并分配不同的引用,如果我们不使用 new 创建对象并具有相同的内容,则它分配与第一个字符串包含的相同引用.

回答by John Jai

Adding to others: new keyword always forcesto create a new object. If you declare like below:

添加到其他人: new 关键字总是强制创建一个新对象。如果你声明如下:

String s1 = "some";
String s2 = "some";

Then using String Pooling mechanism, both references s1 and s2 will refer to the same String object with the value "some".

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

回答by Maroun

When you have

当你有

String str1 = new String("BlaBla");  //In the heap!
String str2 = new String("BlaBla");  //In the heap!

then you're explicitly creating a Stringobject through newoperator (and constructor). In this case you'll have each object pointing to a differentstorage location.

然后您String通过new运算符(和构造函数)显式创建对象。在这种情况下,您将使每个对象指向不同的存储位置。

But if you have:

但如果你有:

String str1 = "BlaBla";        
String str2 = "BlaBla";

then you've implicit construction. Two strings literals share the same storageif they have the same values, this is because Java conserves the storage of the same strings! (Strings that have the same value)

那么你就有了隐式构造。如果两个字符串字面量具有相同的值,则它们共享相同的存储空间,这是因为 Java 保存了相同字符串的存储空间!(具有相同值的字符串)

回答by AmitG

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

both points to same object. for more detail click here

两者都指向同一个对象。欲了解更多详情,请点击这里

回答by Vorsprung

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

Do they point to the same memory location?

它们指向相同的内存位置吗?

I originally said "no" but in the case above, see the StringPool answer referred to below, it's actually yes..

我最初说“不”,但在上面的情况下,请参阅下面提到的 StringPool 答案,实际上是。

"when we create identical strings (without new keyword), does the content get stored in the memory only once and all the String objects with the same content just refer to the same location"

“当我们创建相同的字符串(没有 new 关键字)时,内容是否只存储在内存中一次,并且所有具有相同内容的 String 对象只是引用相同的位置”

...kind of see detailed answer in question "Java Strings and StringPool"

...有点看到问题“Java Strings and StringPool”的详细答案

"The hash codes of s1 and s2 are the same. But are hashcodes dependent directly on memory location of the object?"

“s1 和 s2 的哈希码是相同的。但是哈希码是否直接依赖于对象的内存位置?”

No the hashcodes depend on the content of the String

不,哈希码取决于字符串的内容

回答by Viet Anh Do

YES, Andrew Hare was answer on stack overflow in this link https://stackoverflow.com/a/2486195/4835894.

是的,Andrew Hare 在此链接https://stackoverflow.com/a/2486195/4835894 中回答了堆栈溢出。

Basically, a string intern pool allows a runtime to save memory by preserving immutable strings in a pool so that areas of the application can reuse instances of common strings instead of creating multiple instances of it.

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