代码之家  ›  专栏  ›  技术社区  ›  Ryan Thames

Java中String(String)构造函数的使用[复制]

  •  11
  • Ryan Thames  · 技术社区  · 17 年前

    我读过一些文章和书籍 String s = new String("..."); 几乎应该一直避免。我理解为什么会这样,但使用String(String)构造函数有什么用吗?我不认为有,也没有看到任何其他证据,但我想知道SO社区中是否有人知道它的用途。

    6 回复  |  直到 7 年前
        1
  •  41
  •   Pokechu22    11 年前

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

    事实证明,这个构造函数实际上至少在一种情况下是有用的。如果你看过String源代码,你会发现它不仅有char数组值和字符计数的字段,还有String开头的偏移量的字段。这样String就可以与其他String共享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 s中创建的巨大char数组的引用。这意味着即使我们显式地将String s清零,该数组也不会被垃圾回收!

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

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

    如果旧数组大于字符串中的字符数,则此构造函数实际上会将旧内容复制到新数组中,这一点尚不清楚。这意味着旧字符串内容将按预期被垃圾回收。快乐快乐喜悦。

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

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

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

        2
  •  11
  •   Douglas Leeder    17 年前

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

        3
  •  8
  •   Community Mohan Dere    9 年前

    只是为了扩展 Douglas's answer *,我可以举一个明确的例子来说明我在哪里使用过它。考虑阅读一个有数千行的词典文件,每行只有一个单词。阅读此文最简单的方法是使用 BufferedReader.readLine() .

    不幸的是, readLine() 默认情况下,分配80个字符的缓冲区作为预期的行长度。这意味着通常它可以避免无意义的复制——浪费一点内存通常也不算太糟糕。然而,如果你在应用程序运行期间加载一个短单词词典,你最终会永久浪费大量内存。我的“小应用程序”消耗的内存比它应该做的要多得多。

    解决方案是改变这一点:

    String word = reader.readLine();
    

    进入这个:

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

    当然,有评论!

    * 我不记得这件事发生时我是否和道格拉斯一起工作,或者他回答这个问题只是巧合。

        4
  •  0
  •   raupach    17 年前

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

        5
  •  0
  •   Michael Myers KitsuneYMG    17 年前

    来自 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){.....}
    
        6
  •  -2
  •   Martin Thurau    17 年前

    如果你需要,就用它 复制 如果你不想给原始字符串一个句柄,可以使用原始字符串的句柄。但由于字符串是不可变的,我看不到它的用例 这 ;)