9

我知道如果一个字符串是用文字初始化的,那么它会在字符串池中分配一个空间,如果用新的关键字初始化它会创建一个字符串的对象。但我对下面写的一个案例感到困惑。

我的问题是,如果使用 new 关键字创建字符串,然后使用文字更新它的值怎么办?

例如

String s = new String("Value1");  -- Creates a new object in heap space

那么如果写下一条语句如下。

s = "value2";

所以我的问题是,

1 它会在字符串池中创建字符串文字还是会更新该对象的值?

2 如果它在字符串池中创建一个新的文字,当前存在的对象会发生什么?它会被销毁还是会一直存在,直到调用垃圾收集器。

这是一个小字符串,如果字符串包含数千个字符,那么我只是担心它使用的空间。所以我的关键问题是空间。

分配文字后,它会立即从堆中释放空间吗?

谁能解释从第一条语句到第二条语句的值是什么以及内存区域(堆和字符串池)会发生什么。

4

2 回答 2

9

修改Strings

运行时不更新

s = "value2";

在 Java 中,除了原始类型之外,所有其他变量都是对对象的引用。这意味着 onlys指向一个新值。

不变性保证对象的状态在构造之后不能改变。换句话说,没有办法修改StringJava中任何对象的内容。例如,如果您声明s = s+"a";您已经创建了一个字符串,它会以某种方式存储新文本。

垃圾收集

这个答案已经提供了深入的答案。如果您不想阅读完整答案,请在下方简短摘要,但它会省略一些细节。

默认情况下new String(...),对象不会被实习,因此垃圾收集的正常规则适用。这些只是普通的对象。

代码中的常量字符串通常不会被删除,因为最终您可能会引用这些字符串。

然而,答案中有一个旁注,有时类是动态(卸载)加载的,在这种情况下,可以从池中删除文字。


要回答您的其他问题:

分配文字后,它会立即从堆中释放空间吗?

,那不会很有效:垃圾收集器需要分析要删除的对象。您可能与其他对象共享了对旧字符串的引用,因此不能保证您可以回收该对象。此外,存储不再有用的数据并没有太大的问题,只要您不需要向操作系统请求额外的内存(与您的计算机相比,只要您可以将所有数据存储在硬盘驱动器上,您不必担心无用的文件,从您必须购买额外驱动器的那一刻起,您可能会先尝试删除一些文件)。分析需要一些计算工作。通常,垃圾收集器仅在(几乎)内存不足时运行。所以你不应该

谁能解释从第一条语句到第二条语句的值是什么以及内存区域(堆和字符串池)会发生什么。

你的第一个字符串:

String s = new String("Value1");

是对堆的引用。如果您调用该命令,它将在堆上为字符串分配空间。

现在如果你打电话:

s = "value2";

"value2"String Pool的一个元素,它会一直保留在那里直到你的程序结束。

由于您不再引用旧字符串 ( value1)。该对象是收集的候选对象。如果垃圾收集器稍后经过,它将从堆中删除对象并将空间标记为空闲。

于 2015-09-14T12:11:34.617 回答
0

如果您需要更改字符串,您始终可以创建一个包含修改的新字符串。

  • Java 定义了一个 String 的对等类,称为 StringBuffer,它允许更改字符串。
于 2015-09-14T12:32:46.283 回答