String
string字符串底层是一个被final关键字修饰的char[],所以实现细节上是不允许改变的。这就是String类的Immutable(不可变)属性,所以程序中出现字符串拼接的工作是要生成新的String对象,效率是非常底下的。
- 首先执行String string ="abc"在堆内存中开辟一块空间存储abc;
- 执行string+="def"的时候需要先在对内存中开辟一块空间存储def,然后再在堆内存中开辟一块空间存储最终的abcdef,然后将string的引用指向该堆内存空间。可以发现执行这样的短短两行代码需要在堆内存中开辟三次内存空间,造成了对内存空间资源的极大浪费。
发现Stringbuilder和Stringbuffer都是继承了abstractStringbuilder这个抽象类,然后实现了Serializable, CharSequence接口。其次Stringbuilder和Stringbuffer的内部实现其实跟String是一样的,都是通过一个char类型的数组进行存储字符串的,但是是String类中的char数组是final修饰的,是不可变的,而StringBuilder和StringBuffer中的char数组没有被final修饰,是可变的。这就是StringBuilder和StringBuffer和String的区别。
StirngBuffer:
(效率不如StringBuilder,但远比String要高)
StringBuffer相对于StringBuilder效率要相对低一点,但也远比String要高的多。效率低的原因:对于StringBuffer来说更多的考虑到了多线程的情况,在进行字符串操作的时候,它使用了synchronize关键字,对方法进行了同步处理。
因此StringBuffer适用于多线程环境下的大量操作。
StringBuilder:
(没有考虑线程安全问题)
线程安全与线程不安全:
在进行多线程处理的时候,如果多个线程对于这一个对象同时产生操作,会产生预期之外的结果。对于StringBuilder来说,执行效率虽然高,但是因为线程不安全,所以不建议在多线程的环境下对同一个StringBuilder对象进行操作。
因此StringBuilder适用于单线程环境下的大量字符串操作。
---- | 执行速度 | 线程安全 | 使用场景 |
---|---|---|---|
String | 最差 | 线程安全 | 少量的字符串操作 |
StringBuffer | 其次 | 线程安全 | 多线程下在字符缓冲区进行大量操作 |
StringBuilder | 最高 | 线程不安全 | 单线程下在字符缓冲区进行大量操作 |
String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,像str="abc"+"de";
字符串连接是通过stringbuilder实施(或stringbuffer)类及其append方法完成的,但后两者的对象是变量,是可以更改的。
如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。