为什么将 “” 附加到字符串可以节省内存?

2022-08-31 06:28:11

我使用了一个包含大量数据的变量,比如说。我想按以下方式使用此字符串的一小部分:String data

this.smallpart = data.substring(12,18);

经过几个小时的调试(使用内存可视化工具),我发现对象字段记住了 中的所有数据,尽管它只包含子字符串。smallpartdata

当我将代码更改为:

this.smallpart = data.substring(12,18)+""; 

..问题解决了!现在,我的应用程序现在使用的内存非常少!

这怎么可能?谁能解释一下?我认为这个小部分一直在引用数据,但为什么呢?

更新:那么我该如何清除大字符串呢?data = new String(data.substring(0,100)) 会做这个事情吗?


答案 1

执行以下操作:

data.substring(x, y) + ""

创建一个新的(较小的)String 对象,并丢弃对 substring() 创建的 String 的引用,从而启用此对象的垃圾回收。

要意识到的重要一点是,在现有字符串上提供一个窗口 - 或者更确切地说,是原始字符串的基础字符数组。因此,它将消耗与原始字符串相同的内存。在某些情况下,这可能是有利的,但如果你想获取子字符串并处理原始字符串(正如你已经发现的那样),这可能会有问题。substring()

请查看 JDK 字符串源代码中的 substring() 方法,了解更多信息。

编辑:为了回答您的补充问题,从子字符串构造一个新的字符串将减少您的内存消耗,前提是您将对原始字符串的任何引用装箱。

注意(2013 年 1 月)。上述行为在 Java 7u6 中已更改。不再使用蝇量级模式,它将按预期工作。substring()


答案 2

如果您查看 的源代码,您会发现它返回:substring(int, int)

new String(offset + beginIndex, endIndex - beginIndex, value);

其中 是原始的 .因此,您将获得一个新的字符串,但具有相同的底层。valuechar[]char[]

当您这样做时,您将获得一个具有新基础的新字符串。data.substring() + ""char[]

实际上,您的用例是唯一应该使用构造函数的情况:String(String)

String tiny = new String(huge.substring(12,18));