这个问题在这里已有答案:
所以,我意识到我要问的问题涉及到一次又一次被打死的话题,然而,即使在阅读了我能找到的所有答案和文档之后,我仍然对此感到困惑。字符串实习。也许是因为我对JVM缺乏了解;也许这是由于Java 7中引入的变化使许多上述答案和文档贬值。无论哪种方式,我都被困住了,我希望有人可以帮助我更清楚地理解这个概念......
String a = "text";
String b = new String("text");
在上面的例子中,我理解将创建两个String对象。我也明白在内存中只有一个包含序列't', 'e', 'x', and 't'
的char数组。
但是,内存中的每个字符串对象实际存储在哪里?
如果我读过的话我已经正确读过:变量a
的指示对象将存储在常量池中,而b
的指示对象将存储在堆中,对吧?
如果是这种情况,我对实习池如何维护实习字符串感到困惑。它是否跟踪常量池中定义的字符串以及已从堆中手动实现(调用.intern()
)的字符串? JVM是否创建常量池中定义的字符串对象并将它们加载到实习池中?我很困惑这一切是如何运作的......
再次,抱歉问这样令人困惑/愚蠢的问题,这只是我对JVM
的结构和内部运作相对较新,而且很多都让我头晕目眩。谢谢!
当你声明时,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引用不指向堆上的任何对象,它指向String Memory Pool中的对象(另请注意,内存池仅包含唯一的字符串)。
当你说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()
b
说b = b.intern()
我们可以再测试并获得true
。我希望有所帮助。从版本1.0开始,上面的代码在Java中的工作方式相同(现在它仍然在Java 8中以这种方式工作)。