16

所以,我意识到我要问的问题与一次又一次被殴打致死的话题有关,但是,即使在阅读了我能找到的所有答案和文档之后,我仍然有点困惑字符串实习。可能是因为我对JVM缺乏了解;也许这是由于 Java 7 中引入的更改贬低了许多上述答案和文档。无论哪种方式,我都被卡住了,我希望有人可以帮助我更清楚地理解这个概念......

String a = "text";
String b = new String("text");

在上面的示例中,我知道将创建两个 String 对象。我也明白只有一个 char 数组包含't', 'e', 'x', and 't'内存中的序列。

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

如果我读过的内容我没看错:变量的引用对象a将存储在常量池中,而变量的引用对象b将存储在堆中,对吧?

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

再一次,很抱歉提出如此令人困惑/愚蠢的问题,只是我对它的结构和内部工作方式相对较新,JVM其中很多都让我头晕目眩。谢谢!

4

2 回答 2

8

java中有一个叫做String Memory Pool的东西,当你声明时:

String str1="abc";

它进入那个内存池而不是堆上。但是当你写:

String str2=new String("abc");

它会在堆上创建一个完整的对象,如果您再次编写:

String str3 = "abc"; 

它不会在池上创建更多对象,如果该文字已经存在,它将检查池,并将其分配给它。但是写:

String str4 = new String("abc");

将再次在堆上创建一个新对象

关键是:

一个新对象总是会在堆上创建的次数和你写的一样多:

new String("abc");

但是,如果您继续直接分配字符串而不使用关键字 new,它只会从内存池中被引用(或者如果内存池中不存在则被创建)

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

于 2014-11-30T05:44:17.393 回答
6

当您说new String()您获得了新的Object参考时,请考虑

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

然后首先a == b会显示false,因为它们是不同的引用。如果我们intern() bb = b.intern()我们可以再次测试并获得true. 我希望这会有所帮助。上述代码在 Java 1.0 版本中一直以相同的方式工作(今天在 Java 8 中仍然以这种方式工作)。

于 2014-11-30T05:17:59.150 回答