字符串实习在Java 7+中如何工作? [重复]

问题描述 投票:16回答:2

这个问题在这里已有答案:

所以,我意识到我要问的问题涉及到一次又一次被打死的话题,然而,即使在阅读了我能找到的所有答案和文档之后,我仍然对此感到困惑。字符串实习。也许是因为我对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 jvm heap string-interning
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引用不指向堆上的任何对象,它指向String Memory Pool中的对象(另请注意,内存池仅包含唯一的字符串)。


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。我希望有所帮助。从版本1.0开始,上面的代码在Java中的工作方式相同(现在它仍然在Java 8中以这种方式工作)。

© www.soinside.com 2019 - 2024. All rights reserved.