您可能认为自己想要的一个地方是强制内部字符数组的独特副本,如new String(String)
small=new String(huge.substring(10,20))
但是,不幸的是,此行为是未记录的,并且依赖于实现。
当我将大文件(有些高达20 MiB)读取到字符串中并在事后将其雕刻成行时,我被此刻录了。我最终得到了引用char[]的行的所有字符串,这些字符由整个文件组成。不幸的是,这无意中保留了对整个数组的引用,因为我保留的几行比处理文件的时间更长 - 我被迫使用它来解决这个问题,因为处理20,000个文件非常快地消耗了大量的RAM。new String()
实现不可知的唯一方法是:
small=new String(huge.substring(10,20).toCharArray());
不幸的是,这必须复制数组两次,一次用于 String 构造函数,一次在 String 构造函数中复制。toCharArray()
需要有一种记录的方法通过复制现有字符串的字符来获得新的字符串;或者需要改进的文档以使其更加明确(那里有一个含义,但它相当模糊且可以解释)。String(String)
假设文档未说明的内容的陷阱
为了回应不断出现的评论,观察Apache Harmony的实现是什么:new String()
public String(String string) {
value = string.value;
offset = string.offset;
count = string.count;
}
没错,那里没有底层数组的副本。然而,它仍然符合(Java 7)字符串文档,因为它:
初始化新创建的 String 对象,使其表示与参数相同的字符序列;换句话说,新创建的字符串是参数字符串的副本。除非需要原始的显式副本,否则不需要使用此构造函数,因为字符串是不可变的。
突出部分是“参数字符串的副本”;它没有说“参数字符串和支持字符串的基础字符数组的副本”。
请注意,您编程到文档而不是一个实现。