当前位置: 首页 > 知识库问答 >
问题:

JAVA-8 中堆上的字符串对象数

周枫涟
2023-03-14

从堆栈溢出上的字符串对象数中,我知道如果我们做一些事情,比如:

String s = new String("ABC");

然后我们有两个对象,一个在堆上是字符串,另一个在常量池上,即“ABC”

但今天我进行了堆转储,发现堆上有两个对象。我同样使用MAT工具,请看下面的屏幕截图。

我的问题是,如果堆上有两个对象,一个是< code>Char[]类,另一个是< code>String类,还有一个是常量池,那么这意味着

String s=new String("ABC")将总共创建3个对象。

共有3个答案

徐昕
2023-03-14

每个JavaString对象都有一个私有最终char值[];表示String的不可变内容(参见源代码)。

这似乎反映了您在堆分析中看到的情况。

融伯寅
2023-03-14

< code>char[]是< code>String的内部字段(毕竟,它必须在某个地方存储字符)。

当询问“创建了多少个对象”时,内部字段不计算在内。

如果被问及此操作创建了多少个对象:

Map<Integer, Integer> map = new HashMap<>();

一致意见是“1”。在内部,创建了许多对象(我没有分析过,但是我猜会超过20个),但是实现选择不是问题的一部分。

谭新知
2023-03-14

互联网上似乎有关于字符串文字和字符串池的重复废话。只是为了强调,如何堆在定义:

Java虚拟机规范

Java虚拟机有一个在所有Java虚拟机线程之间共享的堆。堆是运行时数据区域,从中分配所有类实例和数组的内存。

因此,无论虚拟机如何实现它,所有对象都位于堆中,因为这就是术语堆的定义方式。堆是内存,所有对象实例都是从堆中分配的,因此,所有对象都是从堆中分配的。过去,字符串文本的对象和通过 new 创建的对象曾经存在于不同的内存区域中,但所有这些对象仍然是堆的一部分。

在最近的JVM中,所有String实例都在同一个内存区域中创建,无论是为文字创建还是为通过new创建的实例创建。

无论哪种情况,用于管理字符串文字和“interned”字符串的字符串池都是对这些字符串的引用表。表本身可能位于堆之外,而对象则不在堆之外。

在您的示例中,您有两个String实例和一个char[]数组,因为String被实现为char[]数组的包装器,并且两个字符串共享数组。但这是一个实现细节。在其他(较旧的)JVM中,当您使用String(String)构造函数从另一个字符串构造一个字符串时,该数组会被复制。因此在这些JVM中,您的示例将创建两个String实例和两个char[]数组实例。

更花哨的是,使用最新的JVM和适当的配置,JVM将识别具有不同数组但内容相同的String实例,并将它们更改为共享一个数组以减少内存消耗。此功能称为字符串重复数据删除。关于堆栈溢出,请参阅:Java 8 的字符串重复数据删除功能。

 类似资料:
  • 问题内容: 谁能从此链接http://www.javatpoint.com/corejava-interview- questions-3 解释问题87和89 87)在下面的代码中将创建多少个对象? 答案是:只有一个物体 89)在下面的代码中将创建多少个对象? 答案是:两个对象,一个在字符串常量池中,另一个在非池(堆)中。 问题答案: 尽管是用Java编写的类,但它是一种与JVM有特殊关系的特殊类

  • 问题内容: 有没有办法从Java中的String变量创建新类? 另外,如果可能,生成的对象是否必须为Object类型? 也许有更好的方法,但是我希望能够从XML文件中检索值,然后实例化以这些字符串命名的类。这些类中的每一个都实现相同的接口,并从相同的父类派生,因此我将能够在该类中调用特定的方法。 问题答案: 这是你想做的: 请注意,newInstance方法不允许使用参数化的构造函数。(请参阅Cl

  • 我有Json String看起来像这样 并希望将此Json字符串转换为对象的数组列表,并将所有元素放在类(数据Object.class)上并打印元素。 输出为: 我创建的类具有这种形式 我做错了什么?

  • 问题内容: 我有以下问题: 如何将以下代码片段转换为Java 8 lambda样式? 不知道,从以下内容开始: 问题答案: 您需要将自己的流放入列表: 有关其他信息,请访问文档 只是可以写成的另一种形式(因为类型将由编译器推断)

  • 毫无头绪,从以下入手:

  • 问题内容: 之间有什么区别 和 问题答案: 当你使用字符串文字时,可以将字符串嵌入,但是当你使用时,你将获得一个新的字符串对象。 在此示例中,两个字符串文字均引用相同的对象: 在这里,创建了2个不同的对象,它们具有不同的引用: 通常,应尽可能使用字符串文字表示法。它更易于阅读,并且为编译器提供了优化代码的机会。