为什么要将“”添加到字符串保存内存?

我使用了一个有很多数据的变量,比如String data 。 我想用下面的方式使用这个字符串的一小部分:

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

经过几个小时的调试(使用内存可视化工具)后,我发现objects field smallpart记住了所有来自data ,尽管它只包含子字符串。

当我将代码更改为:

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

问题解决了! 现在我的应用程序现在使用的内存很少!

这怎么可能? 任何人都可以解释吗? 我认为this.smallpart一直在引用数据,但为什么?

更新:然后我如何清除大字符串? 将数据=新的字符串(data.substring(0,100))做的事情?


执行以下操作:

data.substring(x, y) + ""

创建一个新的(较小的)String对象,并抛出对由substring()创建的String的引用,从而启用垃圾收集。

要认识到的重要一点是, substring()给出一个窗口到一个现有的String - 或者说,是原始String下的字符数组。 因此它将消耗与原始字符串相同的内存。 这在某些情况下可能是有利的,但是如果您想获取子字符串并处理原始字符串(如您已经发现的那样),则会出现问题。

查看JDK字符串源中的substring()方法以获取更多信息。

编辑:要回答您的补充问题,从子字符串构造一个新的字符串将减少您的内存消耗,只要您bin任何引用原始字符串。

注(2013年1月)。 上述行为在Java 7u6中发生了变化。 flyweight模式不再使用,并且substring()将按照您的预期工作。


如果你看一下substring(int, int)的来源substring(int, int) ,你会看到它返回:

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

其中value是原始char[] 。 所以你得到一个新的字符串,但具有相同的底层char[]

当你这样做时, data.substring() + "" ,你得到一个新的字符串和一个新的基础char[]

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

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

当你使用substring ,它实际上并不创建一个新的字符串。 它仍然引用您的原始字符串,并具有偏移量和大小限制。

所以,为了让你的原始字符串被收集,你需要创建一个新的字符串(使用new String ,或者你有什么)。

链接地址: http://www.djcxy.com/p/78381.html

上一篇: Why does appending "" to a String save memory?

下一篇: PHP socket write and then read is blocking the socket