在Java中,一个字符串可以通过下面两种方法创建。
String x = "abc";
String y = new String("abc");
用双引号创建和用构造函数创建有什么区别那?
双引号vs构造函数
这个问题可以通过下面两个简单的例子来回答。
String a = "abcd";
String b = "abcd";
System.out.println(a == b); // True
System.out.println(a.equals(b)); // True
a==b 为真,是因为在a和b都指向方法区域(保存常量池、字段和方法数据)中相同的字符串常量。
当一个字符串常量被创建多次,只有一份字符串的值被保存。这被叫做“string interning”
所有编译时候的字符串常量在java中都是被自动interned。
String c = new String("abcd");
String d = new String("abcd");
System.out.println(c == d); // False
System.out.println(c.equals(d)); // True
c==d为假是因为c和d分别引用堆中不同点对象。不同的对象当然有不同的内存的引用。
如下图所示:
运行时String Interning
感谢LukasEder (他的建议如下):
String interning 即使两个字符串通过构造函数创建,在运行时候仍然可用。
String c = new String("abcd").intern();
String d = new String("abcd").intern();
System.out.println(c == d); // Now true
System.out.println(c.equals(d)); // True
什么时候使用
因为字符串常量“abcd”也是个字符串类型,而且使用构造函数将创建个额外的对象。因此如果你需要创建一个引用字符串,应该使用双引号。
如果你需要在堆中创建一个新对象,那么应该使用构造函数。
译者说明
- ""号定义的String是在编译时候确定的,然后在运行的时候装载在特定内存区。
- new String()必须在运行时候申请内存。
- new String().intern() Java会在常量池中查找是否有相同的字符串,如果有则返回常量池地址,如果没有将此字符串装载到常量池中,然后返回地址。
- == 对于JavaString来说是比较内存地址是否相同,equals 是比较String的unicode序列是否相同。