我正在研究String API,然后突然发现一个空字符串构造函数,即我们可以使用String s = new String()
来构造一个空的字符串对象。
我想知道它是否有任何用途?
当使用 String s = new String();
时,会在堆上创建一个非文字常量的字符串对象,该对象会被垃圾回收。
而当使用 String s = "";
时,会创建一个字符串常量,如果通过默认加载器引用到该对象,它将永远不会被垃圾回收。
请参考下面链接中提出的问题。虽然这可能与您的问题没有直接关系,但它肯定会帮助您更好地理解这个概念。
""
放在字符串常量池中,而 new String()
放在堆上。 - CᴴᴀZ创建一个空字符串,似乎有一些有限的用途。
如果您将通过拼接构建一个String
,并且不使用例如StringBuilder
,则您的代码可以从以下任一开始。
String result = new String();
String result = "";
String result = "first part of string";
// ...
result += "append to the result";
""
来初始化,因为这可以利用字符串常量池。new String()
。这两者并不等价,因为构造函数会创建一个新实例,但""字面量使用运行时池中的实例。 - Natix一个小例子... 字符串可以被垃圾回收
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” - 这意味着所有已加载类中的字符串字面量都被保存在一个池中,因此通常在内存中只有每个唯一字符串字面量的一个实例。这是“享元模式”的应用,类似的池也被保留用于整数和其他基本包装对象(但仅限于少量小值)。
由于这种机制,即使来自不同类的字符串字面量,它们的身份比较通常也是可能的(尽管为了安全和一致性,您应始终使用“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
不从longString
中复制前10个字符并将它们放入自己的新字符数组中,那么它将引用原始数组,仅使用其中的前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
new String(existingString)
的用途,但问题实际上是关于没有参数的new String()
。 :-/ - ruakh要创建一个空字符串,调用默认构造函数如 String s = new String();
将创建一个没有字符的字符串实例。
String()
的 Javadocs 表示:“请注意,由于字符串是不可变的,因此不必使用此构造函数。” - Steve Kuo