字符串文字是否存储在堆栈中?新的String是否存储在堆栈中?

时间:2012-04-03 10:47:59

标签: java memory-management stack heap

  

可能重复:
  difference between string object and string literal

假设我有两个陈述。

String one = "abc";
String two = new String("abc");

哪一个是堆栈内存并存储在堆中?

这两者有什么区别?

创建了多少个对象以及内存中的引用如何?

最佳做法是什么?

4 个答案:

答案 0 :(得分:22)

所有对象都存储在堆上(包括它们的属性)。 1

局部变量(包括参数)总是包含原始值或引用,并存储在堆栈中。 1

所以,对于你的两行:

String one = "abc";
String two = new String("abc");

堆上有两个对象(两个包含"abc"的String对象)和两个引用,每个对象一个,在堆栈上(提供onetwo是本地的变量)。

(实际上,准确地说,当涉及到诸如字符串文字之类的实习字符串时,它们存储在所谓的字符串池中。)

  

创建了多少个对象以及内存中的引用是什么?

有趣的是,你问,因为字符串在Java语言中是特殊的。

但有一件事是保证:每当您使用new时,您确实会获得参考。这意味着two引用与one相同的对象,这意味着在这两行代码之后堆上将有两个对象。


1)从形式上讲,Java语言规范没有规定如何或在何处将值存储在内存中。然而,这(或其变体)通常是如何在实践中完成的。

答案 1 :(得分:7)

第一个被称为 String Literal ,并在程序的编译时创建,第二个是字符串对象并在运行时创建。

在第二种情况下使用 new 关键字,因此它在堆中分配。

在第一种情况下,使用名为实习的机制创建对象。当您尝试创建另一个表示相同字符序列的字符串文字时,则不会创建新的对象编译器,而是引用先前创建并存储在字符串池中的字符串

答案 2 :(得分:4)

只有基本类型的实例(int,long,...)才会保存在堆栈中。引用类型的所有实例(StringIntegerLongYourTypeHere,...)都保存在堆中。

UPDATE 正如注释中所指出的,对引用类型实例的引用(即非基本类型 - Object及其'后代)可以保存在堆栈中。这些是你的局部变量。

这不是“最佳实践”,它是JVM的工作方式,你无法改变它。

答案 3 :(得分:3)

在您的情况下,创建了2个String对象。 通常,所有对象都在堆上创建。但是,由于String 1是字符串文字,因此它将存储在字符串池中(在PermGen中)。您还可以使用intern()方法将字符串添加到字符串池并获取对它的引用。

如果您发布的声明位于方法中,则引用将存储在堆栈中,但不会存储在对象本身中。

至于,我认为最好的做法是: 字符串一=“abc”

这有两个原因:

  1. 代码更清晰
  2. 可以将实际字符串与==进行比较,这比等于快。但是在你比较它之前,你需要intern()任何非文字字符串。
  3. 编辑: 您可能有兴趣查看此链接:Escape Analysis in Java SE 7。它提供了一些影响对象分配的HotSpot相关优化。