我正在研究字符串 API,突然我遇到了一个字符串空构造函数,即我们可以使用构造一个空字符串对象String s = new String()
我想知道它有什么用吗?
当然.....
String s = new String();
将在堆上创建一个非文字字符串对象,该对象将被垃圾收集。
然而
String s = "" ;
将创建一个 String Literal。如果它可以通过默认加载器访问,则永远不会被垃圾收集。
请参阅下面的此链接到我提出的问题。这可能与您的问题没有直接关系,但它肯定会帮助您牢牢掌握这个概念。
它创建空字符串,这似乎有一些有限的用途。
如果您将通过连接来构建 aString
并且不使用 eg StringBuiler
,则您的代码可以从以下内容之一开始。
String result = new String();
String result = "";
String result = "first part of string";
// ...
result += "append to the result";
前两个不等价,您应该更喜欢初始化 with ,""
因为这可以利用string interning。
小例子......字符串可以被垃圾收集
System.out.println(1 + new String() + 2);
代替
System.out.println(1 + "" + 2);
根据文档,此构造函数创建一个空序列。
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.
如果你想要一个空序列,这是有道理的。
但通常情况下,在对它进行更改之前没有必要使用空构造函数,因为您没有更改字符串。实际上,例如,当您使用运算符 += 进行更改时,您正在创建另一个不可变字符串,而不是更改一个。
检查关于这个主题的这个问题:字符串对象如何工作(如不可变对象)?
因为 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
要创建一个空字符串,调用默认构造函数为 String s new String();
将创建一个没有字符的 String 实例。