在查看在线代码示例时,我有时会通过使用 new 运算符将 String 常量分配给 String 对象。
例如:
String s;
...
s = new String("Hello World");
当然,与
相比s = "Hello World";
我不熟悉这种语法,也不知道其目的或效果是什么。 由于字符串常量通常存储在常量池中,然后以 JVM 用于处理字符串常量的任何表示形式存储,是否会在堆上分配任何内容?
最佳答案
你可能认为你想要new String(String)
的一个地方是强制内部字符数组的不同副本,如
small=new String(huge.substring(10,20))
但是,不幸的是,这种行为没有记录在案并且依赖于实现。
当我将大文件(一些高达 20 MiB)读入字符串并在事后将其雕刻成行时,我被这个烧伤了。我最终得到了引用由整个文件组成的 char[] 的行的所有字符串。不幸的是,这无意中保留了对整个数组的引用,因为我坚持的几行比处理文件的时间更长——我被迫使用 new String()
来解决它,因为快速处理 20,000 个文件会消耗大量 RAM。
执行此操作的唯一与实现无关的方法是:
small=new String(huge.substring(10,20).toCharArray());
不幸的是,这必须复制数组两次,一次用于 toCharArray()
,一次用于 String 构造函数。
需要有记录的方法来通过复制现有字符串的字符来获取新字符串;或者 String(String)
的文档需要改进以使其更加明确(那里有一个暗示,但它相当模糊并且可以解释)。
假设文档未说明内容的陷阱
针对不断出现的评论,观察 new String()
的 Apache Harmony 实现是什么:
public String(String string) {
value = string.value;
offset = string.offset;
count = string.count;
}
没错,那里没有底层数组的副本。然而,它仍然符合 (Java 7) String 文档,因为它:
Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string. Unless an explicit copy of original is needed, use of this constructor is unnecessary since Strings are immutable.
突出的部分是“参数的副本字符串”;它没有说“参数字符串的副本和支持该字符串的底层字符数组”。
注意您对文档而不是一个实现进行编程。
关于java - Java中表达式 "new String(...)"的目的是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/390703/