在java中,我们经常使用字符串类型,那么我们所见到的String、StringBuffer、StringBuilder的区别到底是什么呢?
先看以下整理的区别表格:
String | StringBuffer | StringBuilder | |
是否可变 | 不可变,String 是 final 类,不能被继承。对于已经存在的 Stirng 对象,修改它的值,就是重新创建一个对象。 | 可变,使用 append() 方法修改 Stringbuffer 的值,修改的操作不会产生新对象 | 可变类,速度相对于StringBuffer速度更快 |
是否线程安全 | 线程安全 | 线程不安全 | |
使用线程场景 | 多线程操作字符串 | 单线程操作字符串 |
一.String类
String类 是被final修饰的,故String类实例化的对象为不可变的对象。如下所示:
如果要修改已经存在的String 对象的值 ,则需要新建String对象。
例如以下代码:
public class Test {
public static void main(String[] args) {
String str = "Hello ";
str = str + "World ";
System.out.println(str);
}
}
在这段代码执行过程中,对于String对象str,修改其值的对象改变过程如下:
可以看到,对于这段代码,使用String类的情况下,简单的两个字符相加的操作,底层实际上是开辟了三次内存空间,如果我们需要频繁的在原有的字符串后面添加字符以修改字符串的值,那么对于内存空间是极大的浪费,内存需要被频繁的回收,这样将会大大的降低性能。
如果需要经常进行修改等字符串相关的操作,那么最好使用另外两个操作字符串的类,StringBuffer类和StringBuild类。
二.StringBuffer类和StringBuilder类
需要经常修改字符串,那么最好使用StringBuffer类和StringBuild类,修改的过程中并不会产生新的未使用对象。使用 str.append()和 str.insert() 方式进行修改, 使用toString() 方法转换为字符串。
例如:
StringBuilder str = new StringBuilder("Hello "); str.append("World"); str.insert(2, "ll");
StringBuffer类和StringBuilder类的区别:
- StringBuffer 是线程安全的,而 StringBuilder 不是线程安全的(不能同步访问)
- StringBuilder 的速度较 StringBuffer 更快
StringBuffer为什么是线程安全的呢?我们来看看下面的源码截图:
可以看到,StringBuffer中的很多方法都被synchronized修饰了,说明大部分对stringbuffer的操作都只能单线程处理,所以其是线程安全的,但是也会导致效率较慢的问题。
总结:
(1)如果对于字符串的修改相对少量,应该使用 String;
(2)单线程下,且操作字符串较为频繁,使用 StringBuilder,速度更快,且不产生新对象;
(3)多线程下,且操作字符串较为频繁,使用 StringBuffer,且不产生新对象。