面试题:String和StringBuffer和StringBuilder的区别
面试题:String和StringBuffer和StringBuilder的区别
题目分析
StringBuffer
和StringBuilder
是两个极为相似的两个类,它们都是可变的字符串。可以通过查看源码可知,它们的继承的类,实现的接口都是一样的。这两个类在实现上不同的地方基本有两点:
StringBuffer
在很多方法上加上了关键字synchronized
,而StringBuilder
没有。StringBuffer
新增了一个变量toStringCache
,变量toStringCache
是toString
返回的最后一个值的缓存,每当修改StringBuffer
时清除。
除这两点之外,StringBuffer
和StringBuilder
基本上是一致的,它们的大部分的实现都在于AbstractStringBuilder
这个类上。
对于String
类,我们将String
类的部分源码摘取如下:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
/** 该值用于字符存储。 */
private final char value[];
源码中,使用final
关键字修饰了String
类和value
变量,所以,String
类是不可继承的。String
所表示的字符串,底层是使用一个字符数组来保存的,也就是value
这个变量,此时这个变量也使用final
修饰,表示String
的表示的字符串是不可变的。所以,每次对 String
变量进行修改的时候其实都等同于生成了一个新的 String
对象。
String
对象的字符串拼接其实是被 JVM 解释成了 StringBuilder
对象的拼接,以下面代码为例,下图即是被编译后的字节码,可以看出来String
变量的相加其实被翻译成StringBuilder
的append
方法进行操作。
String x = "abc";
String y = "abc";
String z = x + y + y + y;
题目回答
String
变量不可修改,StringBuffer
和StringBuilder
可以修改StringBuffer
是线程安全的,StringBuilder
不是线程安全的。StringBuffer
使用了缓存区,StringBuilder
没有使用缓存区,所以没有修改数据的情况下,多次调用StringBuffer
的toString
方法获取的字符串是共享底层的字符数组的。而StringBuilder
不是共享底层数组的,每次都生成了新的字符数组。- 因为方法被上锁,所以
StringBuffer
的性能一般会比StringBuilder
差,单线程中建议使用StringBuilder
。 - String对象的相加底层调用的是
StringBuilder
对象,分别调用了append
方法和toString
方法,所以在大量字符串相加时,使用String
对象相加效率低于使用StringBuffer
和StringBuilder
,因为还有有StringBuilder
对象的创建过程和toString
方法中字符数组的拷贝过程。