在Java 7+;中字符串的内部处理是如何工作的;?

在Java 7+;中字符串的内部处理是如何工作的;?,java,string,jvm,heap,string-interning,Java,String,Jvm,Heap,String Interning,因此,我意识到我要问的问题与一个被一次又一次地打得要死的话题有关,然而,即使在阅读了我能找到的所有答案和文档之后,我仍然对字符串实习感到困惑。可能是因为我对JVM缺乏了解;可能是因为Java7中引入的更改降低了前面提到的许多答案和文档的价值。不管怎样,我都被卡住了,我希望有人能帮我更清楚地理解这个概念 String a = "text"; String b = new String("text"); 在上面的示例中,我知道将创建两个字符串对象。我还了解到,内存中只有一个字符数组包含序列't'、

因此,我意识到我要问的问题与一个被一次又一次地打得要死的话题有关,然而,即使在阅读了我能找到的所有答案和文档之后,我仍然对字符串实习感到困惑。可能是因为我对JVM缺乏了解;可能是因为Java7中引入的更改降低了前面提到的许多答案和文档的价值。不管怎样,我都被卡住了,我希望有人能帮我更清楚地理解这个概念

String a = "text";
String b = new String("text");
在上面的示例中,我知道将创建两个字符串对象。我还了解到,内存中只有一个字符数组包含序列
't'、'e'、'x'和't'

但是,每个字符串对象实际存储在内存中的什么位置

如果我读的是正确的:变量
a
的引用将存储在常量池中,而
b
的引用将存储在堆中,对吗

如果是这样的话,我对实习生池如何维护实习生字符串感到困惑。它是否跟踪常量池中定义的字符串以及从堆中手动插入(调用
.intern()
)的字符串?JVM是否创建常量池中定义的字符串对象并将它们加载到intern池中?我不知道这一切是如何运作的


再一次,很抱歉问了这么多令人困惑/愚蠢的问题,只是我对
JVM
的结构和内部工作还比较陌生,很多问题让我头晕目眩。谢谢

当您说
new String()
时,您会得到一个新的
对象
引用,所以请考虑

String a = "text";
String b = new String("text");
System.out.println(a == b);
b = b.intern();
System.out.println(a == b);

然后第一个
a==b
将显示
false
,因为它们是不同的引用。如果我们通过说
b=b.intern()
intern()
b
,我们就可以再次测试并得到
true
。我希望这有帮助。自1.0版以来,上述代码在Java中的工作方式与之相同(现在在Java8中仍然如此)

java中有一种叫做字符串内存池的东西,当您声明:

String str1="abc";
它进入内存池,而不是堆。但当你写作时:

String str2=new String("abc");
如果您再次写入以下内容,则会在堆上创建一个完整的对象:

String str3 = "abc"; 
它不会在池上再创建任何对象,它将检查池,如果该文本已经存在,它将为其分配该文本。但写作:

String str4 = new String("abc");
将再次在堆上创建新对象

关键是:

只要您继续写入,就会在堆上创建一个新对象:

new String("abc");
但是,如果不使用关键字new而直接分配字符串,它将从内存池中被引用(或者如果不在内存池中,则被创建)


intern()
方法查找字符串是否存在于内存池中,如果不存在,则将其添加到内存池并返回对该字符串的引用。因此,使用此方法后,您的字符串引用没有指向堆上的任何对象,而是指向字符串内存池中的对象(另外,请注意,内存池仅包含唯一的字符串)

我建议您阅读所有答案,与旧版本相比,Java 7和8中的字符串实习没有任何根本性的变化。感谢您的快速响应,Elliott。我理解上述两个条件都是正确的。我想更确切地说,让我困惑的是:常量池中指定的字符串值(我已经使用cmd中的命令“javap-c-verbose ClassName.class”读过了)是否被实例化并加载到intern池中(从Java7开始,intern池位于堆中)?常量池在运行时是否为实际实体?(对不起,如果我的问题令人困惑,如果需要澄清,请让我知道)@KyleMart第一个答案是错误的。试试看。我试图解释
intern()
池是如何工作的。我的错。哈哈,我真的想说的是,两个条件中的前一个会产生错误。在写我最后的评论时,我完全失去了理智。第一个条件等于false的原因是因为var a引用intern池中的字符串,而var b引用堆中的字符串,对吗?使我困惑的是实习生池和常数池之间的关系。@ KyimART考虑< Cuth> Stuto.Out.PrtLn(新整数(1024)=整数.ValueOf(1024));代码>那将是错误的,对吗?左操作数创建一个新的整数对象,而右操作数的valueOf方法创建一个val为1024的新整数对象,对其进行缓存,并返回对缓存对象的引用。从jdk 7&8开始,内部字符串对象也存储在堆中。新字符串(“test”).intern()如何放置对象(如果还不存在)?如果1。该文本已在池中,或为2。是否已在堆中?@xploreraj检查intern()的java api文档,它的用途已明确指定。