(1)不可变VS可变
String对象是不可变的,StringBuilder和StringBuffer是可变的。String类中有个char类型的数组value,这个数组用于存储字符序列,并且这个数组用final修饰,只能赋值一次,因此String对象是不可变的,一旦赋值就不能变动。对String对象的改动操作都不是在原有的字符串上进行的,而是重新生成了一个新的字符串对象,也就是说进行改动操作后,最原始的字符串并没有被改变。比如两个字符串的连接操作,首先会创建一个StringBuilder对象,接着调用append()添加另一个字符串,然后再调用StringBuilder的toString()生成合并的字符串,过程中要创建两个对象才能完成连接操作。
StringBuilder和StringBuffer中的value[]数组就是一个普通的数组,完成连接操作可以通过append()方法将新字符串加入value[]数组末尾,所以StringBuilder和StringBuffer是可变类。所以如果对字符串的改动操作比较多的话,要选择StringBuilder或者StringBuffer,选择String的话,JVM会创建很多中间对象,会比较耗时。
(2) StringBuilder和StringBuffer比较
StringBuffer是线程安全的,StringBuilder不是线程安全的。StringBuilder和StringBuffer拥有的成员变量以及成员方法基本相同,但是StringBuffer中的大部分成员方法用synchronized修饰,也就是StringBuffer是线程安全的,StringBuilder不是线程安全的,在多线程环境下,如果要保持数据同步的话,要选择StringBuffer。但是StringBuilder的效率比StringBuffer要高,如果不考虑线程安全,应该选择StringBuilder。
字符串创建与存储机制
(1) String s = new String(“abc”)
通过new的方式总会生成一个新的字符串对象,首先会在字符串常量池中查找”abc”是否存在,如果存在的话,new String()会在堆中创建一个字符串对象,如果不存在的话,首先会创建一个”abc”字符串对象,然后添加到字符串常量池中,接着在堆中创建一个字符串对象
(2) String s = “abc”
如果字符串常量池中存在”abc”的话,s引用常量池中的对象,不会创建新的对象,如果不存在的话,首先创建这个字符串对象,然后加入到字符串常量池中,再把它的引用返回。
参考链接:
http://www.cnblogs.com/dolphin0520/p/3778589.html
http://www.iteye.com/topic/522167