12

我正在研究字符串 API,突然我遇到了一个字符串空构造函数,即我们可以使用构造一个空字符串对象String s = new String()

我想知道它有什么用吗?

4

6 回答 6

11

当然.....

String s = new String();

将在堆上创建一个非文字字符串对象,该对象垃圾收集。

然而

String s = "" ;

将创建一个 String Literal。如果它可以通过默认加载​​器访问,则永远不会被垃圾收集。

请参阅下面的此链接到我提出的问题。这可能与您的问题没有直接关系,但它肯定会帮助您牢牢掌握这个概念。

字符串字面量池是对字符串对象的引用的集合,还是对象的集合

于 2012-09-14T18:39:46.060 回答
4

它创建空字符串,这似乎有一些有限的用途。

如果您将通过连接来构建 aString并且不使用 eg StringBuiler,则您的代码可以从以下内容之一开始。

String result = new String();
String result = "";
String result = "first part of string";

// ...
result += "append to the result";

前两个等价,您应该更喜欢初始化 with ,""因为这可以利用string interning

于 2012-09-14T18:38:37.933 回答
3

小例子......字符串可以被垃圾收集

System.out.println(1 + new String() + 2);

代替

System.out.println(1 + "" + 2);
于 2012-09-14T19:06:31.337 回答
0

根据文档,此构造函数创建一个空序列。

public String()

Initializes a newly created String object so that it represents an empty character sequence. Note that use of this constructor is unnecessary since Strings are immutable.

如果你想要一个空序列,这是有道理的。

但通常情况下,在对它进行更改之前没有必要使用空构造函数,因为您没有更改字符串。实际上,例如,当您使用运算符 += 进行更改时,您正在创建另一个不可变字符串,而不是更改一个。

检查关于这个主题的这个问题:字符串对象如何工作(如不可变对象)?

于 2012-09-14T18:46:04.383 回答
0

先介绍一下背景

因为 Java 中的字符串是不可变的,所以它们也是“interned”——这意味着加载的类中的所有字符串文字都保存在一个池中,因此通常每个唯一字符串文字一次在内存中只有一个实例。它是享元模式的一种应用,类似的池也用于 Integer 和其他原始包装对象(但仅限于有限数量的小值)。

由于这种机制,通常可以对字符串文字(甚至来自不同的类)进行身份比较(尽管equals在比较字符串时应始终使用方法以确保安全性和一致性):

System.out.println("hello" == "hello"); // true

现在,如果您使用默认字符串构造函数,您将获得一个空字符串的实例,但它是一个实例,如 JavaDoc 中所述:

初始化一个新创建的 String 对象,使其表示一个空字符序列。请注意,由于字符串是不可变的,因此不需要使用此构造函数。

这样的新实例与实习的空字符串不同,导致:

System.out.println(new String() == ""); // false

但正如我所说,只有字符串文字会被自动实习——这意味着由 StringBuilders 手动创建的字符串、从 char 数组等创建的字符串不会被实习。您可以使用String.intern()方法手动将此类字符串放入池中。

现在来看一些真实的场景

好吧,这一切确实很好,但我还没有回答为什么这个构造函数存在。好吧,Java 字符串只是char 数组的智能包装器,一些不同的字符串对象可以共享它们的内部数组。

如果我创建了一个很长的字符串(例如通过从流中读取),那么这个实例不会被实习(如上所述),因此在引用它的变量超出范围后它将被垃圾收集。但如果这样做:

String longString = readVeryLongString();
String shortString = longString.subString(0, 10);

...那么新的shortString将不会从 中复制前 10 个字符longString并将它们放入自己的新 char 数组中。不,它将引用原始数组,仅使用其中的前 10 个字符。

现在,如果 shortString 变量具有更长的生命周期(例如放入某个静态上下文中),那么底层 char 数组将不会被垃圾收集(即使原始longString变量已经超出范围)。这是在 Java 中创建内存泄漏的方法之一。

现在,默认的字符串构造函数来拯救了!如果我将上面的代码更改为:

String longString = readVeryLongString();
String shortString = new String(longString.subString(0, 10));

...然后shortString将是一个新的字符串实例,它通过从subString方法返回的原始字符串中仅复制 10 个所需的字符来创建一个新的内部字符数组。


一篇很好的文章说明了这个主题:

http://illya-keeplearning.blogspot.cz/2009/03/java-string-internals.html

于 2012-09-14T18:50:40.777 回答
-1

要创建一个空字符串,调用默认构造函数为 String s new String();

将创建一个没有字符的 String 实例。

于 2012-09-14T18:43:50.693 回答