【问题标题】:Is a String literal stored on the stack? Is a new String stored on the stack? [duplicate]字符串文字是否存储在堆栈中?新的字符串是否存储在堆栈中? [复制]
【发布时间】:2012-04-17 00:21:23
【问题描述】:

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

假设我有两个陈述。

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

哪个是栈内存,哪个是堆内存?

这两者有什么区别?

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

最佳做法是什么?

【问题讨论】:

标签: java memory-management heap-memory stack-memory


【解决方案1】:

所有对象都存储在堆上(包括其字段的值)。1

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

所以,对于你的两条线:

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

堆上有两个对象(两个包含 "abc" 的字符串对象)和堆栈上的两个引用,每个对象一个引用(前提是 onetwo 是局部变量)。

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

创建了多少对象,内存中的引用情况如何?

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

保证有一件事:无论何时使用new,您确实会得到一个新的引用。这意味着two引用与one 相同的对象,这意味着在这两行代码之后您将在堆上拥有两个对象。


1) 从形式上讲,Java 语言规范没有指定值在内存中的存储方式和位置。然而,这(或它的变体)通常是在实践中完成的。

【讨论】:

  • 好答案。但实际上它不再那么简单了。 JVM 可能会进行逃逸分析并决定直接在堆栈上分配对象,这意味着在方法结束时清理它们是空闲的。但这是您通常不需要了解的高级优化。
  • 当你说“包括他们的属性”时,属性是类成员字段的另一种说法吗?
  • 是的。答案已更新。
【解决方案2】:

只有原始类型(int、long、...)的实例保存在堆栈中。所有引用类型的实例(StringIntegerLongYourTypeHere、...)都保存在堆中。

更新 正如 cmets 中所指出的,对引用类型实例(即非原始类型 -- Object 及其后代)的引用可以保存在堆栈中。这些是你的局部变量。

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

【讨论】:

  • 不,引用不保存在堆中。对象是。
  • @aioobe 修正了使用“...类型的实例”的措辞,以澄清这一点。
  • 维克多,您的回答仍然具有误导性。引用类型变量的值(String a 中的a)可以很好地存储在堆栈中。但是,它引用的 object 存储在堆上。
  • 第二个。如果原始值是类的字段,则可以在堆上分配它们,因为它们将与它们所属的对象一起存储。使用关键字“new”创建的内容进入堆。堆栈值只存在于创建它们的方法范围内。
【解决方案3】:

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

因为您在第二种情况下使用了 new 关键字,所以它被分配在堆中。

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

中的字符串

【讨论】:

  • new String("abc") 将在堆中创建字符串对象,b'coz new keywork 在堆中创建对象。虽然 String str = "abc" 将在字符串池中创建字符串字面量,但字符串池存在于 PeremGen 空间中。
【解决方案4】:

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

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

至于,我认为最佳实践是: 字符串一个="abc"

这有两个原因:

  1. 代码更干净
  2. 可以将内部字符串与 == 进行比较,这比 equals 更快。但是您需要先对任何非文字字符串进行 intern() 才能进行比较。

编辑: 您可能有兴趣查看此链接:Escape Analysis in Java SE 7。它介绍了一些影响对象分配的 HotSpot 相关优化。

【讨论】:

    猜你喜欢
    • 2016-01-12
    • 2017-11-16
    • 2014-04-01
    • 2011-06-25
    • 1970-01-01
    • 2018-04-21
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    相关资源
    最近更新 更多