在查看在线代码示例时,有时会遇到通过使用new运算符将String常量分配给String对象的情况。
例如:
String s; ... s = new String("Hello World");
当然,与
s = "Hello World";
我不熟悉这种语法,也不知道其目的或效果。由于String常量通常存储在常量池中,然后JVM以任何表示形式存储在处理String常量中,因此是否还会在堆上分配任何内容?
你可能需要的一个地方new String(String)是强制子字符串复制到新的基础字符数组,如
small=new String(huge.substring(10,20))
但是,不幸的是,此行为是未记录的,并且取决于实现。
当将大文件(最多20 MiB)读入字符串并在事后将其刻成几行时,我对此感到非常恼火。我最后得到了引用由整个文件组成的char []的所有字符串。不幸的是,与处理文件相比,我无意间对整个数组的引用保留了更长的时间,这比处理文件要更长的时间-我被迫用来new String()解决该问题。
new String()
唯一与实现无关的方法是:
small=new String(huge.substring(10,20).toCharArray());
不幸的是,这必须将数组复制两次,toCharArray()一次在String构造函数中一次。
toCharArray()
需要有一种通过复制现有字符串的字符来获取新String的文档化方法;或String(String)需要改进的文档以使其更明确(此处有隐含含义,但相当含糊且易于解释)。
假设文档没有陈述的陷阱 为了回应不断出现的评论,请观察Apache Harmony的实现new String()是:
public String(String string) { value = string.value; offset = string.offset; count = string.count; }
没错,那里没有底层数组的副本。但是,它仍然符合(Java 7)字符串文档,因为它:
初始化一个新创建的String对象,使其表示与参数相同的字符序列;换句话说,新创建的字符串是参数字符串的副本。除非需要显式的原始副本,否则不需要使用此构造函数,因为字符串是不可变的。
突出的部分是“参数字符串的副本”;它不会说“参数字符串和支持该字符串的基础字符数组的副本”。
请注意,你应按照文档而不是一种 实现编程。