最近学到StringBuilder,就想搞明白关于String,StringBuilder,StringBuilder的区别,现在我就整理一下。
关于这三个类在字符串界的位置是不言而喻的,那么它们之间有啥重要的区别和有优点呢?
(1)三者在执行速率方面的比较:StringBuilder > StringBuffer > String;
(2)String唯一的好处:它是常量,程序的至始至终不会改变,存放在方法区的常量池中,可以供多个线程共享;
StringBuilder字符串变量,不是线程安全的,不能被多个线程共享,类中的方法没有使用synchronized 加锁机制;
StringBuffer字符串变量,是线程安全的,能被多个同步线程共享,类中的方法都被synchronized 关键字加锁。
(3)String < (StringBuilder,StringBuffer)的原因:
String是字符串常量,是不可以改变的;StringBuilder和StringBuffer是变量,因此是可以改变的!
【示例代码】
String str = "dog ";
str = str + "is animal";
System.out.println(str); //dog is animal
解释:明明改变了String 的值,为什么会说没有改变呢?其实这是一种欺骗,JVM是这样解析这段代码的:首先创建一个字符串对象,赋值为"dog",将其对象引用赋值给str引用变量;然后执行第二段代码,JVM会自动的默认原字符串对象失效,自动的新创建一个新的字符串对象,赋值为"dog is animal",将其str引用指向新字符串,等到下一次JVM的GC(垃圾回收)自动将其原字符串对象所占内存回收,可想而知这样执行效率有多低!
而StringBuffer和StringBuilder变量就不一样了,它们是字符串变量,调用append()方法,会自动的将其追加的字符串追加到原串的尾部,不会新分配堆内存创建新对象,当然速率就很快啦!
StringBuffer strBuffer = new StringBuffer("dog ");
strBuffer.append("is animal");
System.out.println(strBuffer); //dog is animal
【实例代码】
public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
解释:可以看到StringBuffer类中的append()方法在进行字符串追加时,自动的在其方法上通过 synchronized关键字加锁,从而实现了多线程在访问该字符串变量中的字符串时,就是同步访问;加锁会使程序中的字符串访问安全,但是效率十分缓慢,非常低(相比StringBuffer来说很低,但是不需要重新分配内存,效率又比String类高);
【实例代码】
StringBuilder strBuilder = new StringBuilder("dog ");
strBuilder.append("is animal");
System.out.println(strBuilder); //dog is animal
使用append()方法时,查看源代码:
public StringBuilder append(String str) {
super.append(str);
return this;
}
可以看到StringBuilder 类中的append()方法在进行字符串追加时,自动的在其方法上未使用synchronized 关键字加锁,因此不能保证多线程中访问字符串安全问题;并且也没有重新的分配内存,故而访问的效率最高。
当字符串被多个线程使用时,JVM不能保证StringBuilder的操作是安全的,虽然它的速度最快,但
是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以
大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。
1.如果要操作少量的数据使用:String
2.单线程操作字符串缓冲区下操作大量数据使用:StringBuilder
3.多线程操作字符串缓冲区下操作大量数据使用:StringBuffer