面试/笔试常见问题:String、StringBuffer和StringBuider的区别?
透过源码看本质:
1、String
在源码中可以看出String中,用来存储字符串的字符数据value[]通过final修饰,所以String对象是不可变的!!
注意:是对象哦~但是指向对象的引用还是可以变的!涉及常量池、堆和栈后面详谈。
延伸问题:为什么String要被设计成final???
我的理解
- final意味着不可变,不可变则在多线程情况下,线程问题安全
- 不可变意味着存储在常量池中,可以提升性能
- 其实在java中,八大基本数据类型的包装类型:Byte、Short、Integer、Long、Double、Float、Boolean、Charater都是设计成final类型。这样可以保证数据的安全性。
2.StringBuilder和StringBuffer都是继承AbstractStringBuilder,在AbstractStringBuilder中,也是使用字符数组保存字符串,但是char[] value没有使用final修饰,所以两者的对象都是可变的。
那二者的区别在于:StringBuilder是线程不安全的,StringBuffer是线程安全的。
原因:StringBuffer重写继承自AbstractStringBuilder的方法的时候,对所有的方法添加synchronize修饰词。
例如:
- StringBuffer
- StringBuffer
总结:
1、线程安全方面:
String对象不可变,存储在常量池中,线程安全。
StringBuffer对继承自父类的公共方法重写加锁,所以线程安全。
StringBuilder没有做处理,线程不安全。
2、性能方面
String类型进行改变的时候,都会生成一个新的对象,把指针指向新的对象。
StringBuffer和StringBuilder每次都是对本身进行操作。相同情况下,使用StringBuilder比StringBuffer性能要高出10%~15%左右的性能,都是多线程情况下会有线程不安全的风险。
3、使用推荐
- 修改操作少,且少量数据的用String
- 单线程操作字符串缓冲区下大量数据:StringBuilder
- 多线程操作字符串缓冲区下大量数据:StringBuffer。