1.Java中的String
Java中存在一个strings pool的东东,里面装的都是些不可变的字符串,比如有:"abc","hello","1111"等等。这些字符串有一个特点,那就是不可改变。其实,这只是一个形象化的说法,准确的说,strings pool里存放的不是对象,而是引用,引用的对象也是在堆上分配的, strings pool本质上是 一个constant table,这个表里的条目都是引用,当class文件被加载(load)时,jvm搜寻类似于"abc"的字符串,以此为内容在堆上生成对象,并在constant table中保存此对象的引用。
当在程序中有下面的语句
String s1 = "abc";
jvm在class文件加载时,就会在堆上生成一个内容为abc的对象,并在constant table中保存它的引用。形象化的, strings pool中增加了一个abc对象。 当然,如前所述,这个对象的内容abc是不能改变的。
维护这样一个strings pool是有意义的,当代码中出现下面的语句时,strings pool里内容为abc的对象即可重用。
String s2 = "abc";
此时,s1和s2都引用strings pool里的内容为abc的对象,因此,它们是相等的,即下面的代码返回true
s1==s2; //true
看下面的代码
String s3 = new String("abc");
一方面,由于new操作符的存在,在程序运行时,Java会在堆里生成一个String对象,它的内容为abc。另一方面,jvm加载class文件,扫描到此行代码时,如果之前代码中有"abc",就不再为其在堆里生成对象, 否则 ,在堆里生成 内容为abc的对象,并保存其引用在 constant table里。
在实际应用中,经常要对字符串做某些操作,比如字符串的拼接。下面代码演示了关于字符串拼接的过程。
String s4 = "hello";
String s5 = "world";
String s6 = s4 + s5;
为了得到s6,对s4和s5做了拼接,结果不仅在strings pool里生成了内容分别为hello和world的两个对象,又在堆里生成了一个新的对象,它的内容为helloworld,这个新对象不会在constant table中保存引用,但在我们的代码里,用s6来引用它。拼接后的两个对象(s4和s5),如果不重用,就没有存在的必要了,但是Java仍然要在 constant table 中维护它们的引用,它们在堆里也要占用空间,系统开销就出现了,而当strings pool里的此类对象过多时,必然要影响程序的性能。这还有一个问题,执行下面的代码
s4=null;
s5=null;
这样gc是否会回收s4和s5引用的对象呢?当然不能,因为在constant table中还保留一个我们看不到的对这两个对象的引用,所以gc无能为力了。
为了解决"垃圾"对象泛滥的问题,我们需要一个可变的字符串对象,操作该对象而不导致新的对象产生,只是让该对象做些适当的改变而已。StringBuffer类就这样应运而生了。
2.StringBuffer
....
参考文献: