一尘不染

Java中“ new String(…)”表达式的目的是什么?

java

在查看在线代码示例时,有时会遇到通过使用new运算符将String常量分配给String对象的情况。

例如:

String s;
...
s = new String("Hello World");

当然,与

s = "Hello World";

我不熟悉这种语法,也不知道其目的或效果。由于String常量通常存储在常量池中,然后JVM以任何表示形式存储在处理String常量中,因此是否还会在堆上分配任何内容?


阅读 397

收藏
2020-02-27

共1个答案

一尘不染

你可能需要的一个地方new String(String)是强制子字符串复制到新的基础字符数组,如

small=new String(huge.substring(10,20))

但是,不幸的是,此行为是未记录的,并且取决于实现。

当将大文件(最多20 MiB)读入字符串并在事后将其刻成几行时,我对此感到非常恼火。我最后得到了引用由整个文件组成的char []的所有字符串。不幸的是,与处理文件相比,我无意间对整个数组的引用保留了更长的时间,这比处理文件要更长的时间-我被迫用来new String()解决该问题。

唯一与实现无关的方法是:

small=new String(huge.substring(10,20).toCharArray());

不幸的是,这必须将数组复制两次,toCharArray()一次在String构造函数中一次。

需要有一种通过复制现有字符串的字符来获取新String的文档化方法;或String(String)需要改进的文档以使其更明确(此处有隐含含义,但相当含糊且易于解释)。

假设文档没有陈述的陷阱
为了回应不断出现的评论,请观察Apache Harmony的实现new String()是:

public String(String string) {
    value = string.value;
    offset = string.offset;
    count = string.count;
}

没错,那里没有底层数组的副本。但是,它仍然符合(Java 7)字符串文档,因为它:

初始化一个新创建的String对象,使其表示与参数相同的字符序列;换句话说,新创建的字符串是参数字符串的副本。除非需要显式的原始副本,否则不需要使用此构造函数,因为字符串是不可变的。

突出的部分是“参数字符串的副本”;它不会说“参数字符串和支持该字符串的基础字符数组的副本”。

请注意,你应按照文档而不是一种 实现编程。

2020-02-27