一旦 String 对象被创建,我们就无法修改它但是如果我们对它进行任何操作,JVM 将创建 New Object。在这里,通过创建新对象,JVM 会消耗更多内存。然后我认为这会导致内存问题,对吗?
9 回答
你是对的。绝对值得注意这个问题,即使它不会每次都影响您。
正如您所说,字符串在创建后无法更改 - 它们是不可变的,并且它们不会公开许多更改它们的方法。
但是,诸如 split() 之类的操作将在后台生成额外的字符串对象,并且如果您持有对它们的引用,那么这些字符串中的每一个都会产生内存开销 。
正如其他海报所指出的,对象会很小,垃圾收集通常会在旧对象超出范围后对其进行清理,因此您通常不必担心这一点。
但是,如果您正在做一些特定的事情并持有大量的字符串引用,那么这可能会咬到您。
根据您的用例 查看字符串实习,注意链接页面上的警告。
有两点需要注意:
1) 硬编码的字符串文字将被Java自动实习,减少这种影响。
2) + 运算符在这方面更有效,它将在下面使用字符串生成器,从而提供性能和内存优势。
不,那不是。如果您不持有指向 String 实例的强链接,它们最终将被垃圾收集器收集。
例如:
while (true) {
new String("that is a string");
}
在这个片段中,你不断地创建新的对象实例,但是你永远不会得到 OutOfMemoryException,因为创建的实例变成了垃圾(显然没有强链接)。
你必须知道的最大的内存问题是从一个大字符串中提取一个小子字符串。该子字符串共享原始字符串的 char 数组,即使原始字符串被 gc'd,巨大的 char 数组仍将被子字符串引用。解决方法是使用new String(hugeString.substring(i))
.
它为新对象消耗更多内存,这是正确的。但这个事实本身并没有造成问题,因为垃圾收集器会迅速回收所有不可访问的内存。当然,您可以通过创建指向新创建的字符串的链接将其变成问题,但这将是您的程序的问题,而不是 JVM 的问题。
据我所知,StringBuilder(或用于线程安全的StringBuffer)对于管理 String 并使它们可变非常有用。
在一个巨大的字符串中操作一些字符不会“吃掉”内存中的许多字节。
它也更强大/更快的连接。
由于字符串实例是不可变的,它可以被 jvm 重用。String 类使用享元设计模式实现,用于避免内存问题。
产生的问题是产生垃圾的事实。虚拟机通过调用垃圾收集器来释放该垃圾使用的内存来解决此问题。
一旦不再使用旧对象,垃圾收集器就可以将其删除。(这将在任何内存问题出现之前完成)。
如果要防止复制数据,请使用 StringBuilder。