在Java中使用String(String)构造函数

时间:2009-01-21 14:56:05

标签: java string coding-style

我读过文章和书籍时,应该始终避免使用String s = new String("...");。我明白为什么会这样,但是使用String(String)构造函数有什么用处吗?我认为没有,也没有看到任何其他证据,但我想知道SO社区中是否有人知道有用。


完全重复: What is the purpose of the expression new string in java?

6 个答案:

答案 0 :(得分:39)

这篇文章很好:String constructor considered useless turns out to be useful after all!

  

事实证明,这个构造函数在至少一种情况下实际上是有用的。如果你曾经看过String源代码,你会发现它不仅包含char数组值和字符数的字段,而且还包含字符串开头的偏移量。这样,Strings可以与其他字符串共享char数组值,通常是调用substring()方法之一。 Java在几年前的jwz'Java咆哮中受到了严厉的惩罚:

     

这种开销的唯一原因是String.substring()可以返回共享相同值数组的字符串。这样做是为了向每个String对象添加8个字节而不是净节省......

     

除了节省的字节,如果你有这样的代码:

// imagine a multi-megabyte string here  
String s = "0123456789012345678901234567890123456789";  
String s2 = s.substring(0, 1);  
s = null;
     

现在你将拥有一个String s2,虽然它似乎是一个单字符的字符串,但它拥有对String中创建的巨大字符数组的引用。这意味着数组不会被垃圾收集,即使我们已经明确地删除了String!

     

对此的修复是使用我们之前提到的“无用的”String构造函数,如下所示:

String s2 = new String(s.substring(0, 1));  
     

如果旧数组大于字符串中的字符数,则此构造函数实际上将旧内容复制到新数组并不为人所知。这意味着旧的String内容将按预期进行垃圾回收。快乐幸福快乐的喜悦。

最后,Kat Marsen提出了这些观点,

  

首先,字符串常量永远不会被垃圾收集。其次,字符串常量是实习的,这意味着它们在整个VM中共享。这节省了内存。但它并不总是你想要的。

     

String上的复制构造函数允许您从String文本中创建私有String实例。这对于构造有意义的互斥对象(出于同步目的)非常有价值。

答案 1 :(得分:11)

如果我没记错的话,唯一“有用”的情况是原始字符串是更大的后备数组的一部分。 (例如,创建为子字符串)。如果你只想保留小的子串并且垃圾收集大缓冲区,那么创建一个新的String可能是有意义的。

答案 2 :(得分:8)

为了扩展Douglas's answer *,我可以给出一个我用过它的确凿例子。考虑阅读一个包含数千行的字典文件,每个行只有一个单词。阅读本文的最简单方法是使用BufferedReader.readLine()

不幸的是,readLine()默认情况下会将80个字符的缓冲区分配为预期的行长度。这意味着它通常可以避免无意义的复制 - 而且浪费的内存通常不会太糟糕。但是,如果您在应用程序的持续时间内加载了短字词词典,最终会导致大量内存被永久浪费。我的“小应用程序”吸取的内存远远超过应有的记录。

解决方案是改变这个:

String word = reader.readLine();

进入这个:

String word = new String(reader.readLine());

......当然还有评论!

*我不记得当道格拉斯真的出现时,我是否与道格拉斯合作,或者他回答这个问题是否巧合。

答案 3 :(得分:0)

构造函数很大程度上是冗余的,不建议用于一般用途。除了创建现有字符串变量的独立副本外,很少使用带String参数的String构造函数。基本上用它来“澄清”你的代码。没什么。

答案 4 :(得分:0)

来自javadoc

/**
 * Initializes a newly created {@code 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 {@code original} is needed, use of this constructor is
 * unnecessary since Strings are immutable.
 *
 * @param  original
 *         A {@code String}
 */
public String(String original){.....}

答案 5 :(得分:-2)

如果您不想提供原始字符串的句柄,则需要原始字符串的副本时使用它。但由于字符串是不可变的,我没有看到用例 this ;)