String str=new String("abc");
首先我们要知道的是这句话生成了两个String对象,一个是new String("abc")在常量池中产生了一个"abc"对象,另外一个对象是在堆中复制了一份字符串池中的"abc",并将这个对象的引用交给str使用,str只是一个引用变量.
再了解为什么产生两个String对象之前我嗯先要明白什么是引用变量和对象,对象一般在通过new在堆中创建,而str只是一个引用变量.
引用变量与对象的区别:
字符串文字"abc"是一个String对象,文字池(pool of literal strings)和堆(heap)中的字符串对象.
我们举个例子再来说明一下什么是引用变量和对象,
Object Demo;
这句话只是声明了一个类Object的引用变量Demo(我们常将之称为句柄),而对象一般通过new方法来进行创建.
并且在java中所有的字符串文字(字符串常量)都是一个String的对象.
String字符串对象创建过程:
由于字符串对象的大量使用(它是一个对象,一般而言对象总是在堆(heap)中分配内存),Java中为了节省内存空间和运行时间(如比较字符串时,==比equals()快),在编译阶段就把所有的字符串文字放到一个文字池(pool of literal strings)中,而运行时文字池成为常量池的一部分。文字池的好处,就是该池中所有相同的字符串常量被合并,只占用一个空间。
String s1 = "abc" ;
String s2 = "abc" ;
if( s1 == s2 ) System.out.println("s1,s2 refer to the same object");
else System.out.println("trouble");
在上述代码中我们只在常量池中创建了一个"abc"字符串对象,而分别定义了两个引用变量s1和s2分别去常量池中指向他们.
String str=new String("abc");
这个时候我们再来回到原问题,现在看String s = new String("abc");语句,
这里"abc"本身就是文字池中的一个对象,而在运行时执行new String()时,将文字池pool中的对象复制一份放到堆heap中,并且把heap中的这个对象的引用交给str持有。所以,这条语句就创建了2个String对象。