这几天基本上都在给大家分析一些面试题。
希望通过一些比较具体化,形象化的描述来让大家能理解这些比较抽象的东西。
今天就给大家分析下String、StringBuffer和StringBuilder的区别。
01String对于StringBuffer和StringBuilder来说的区别
先说说String和其他两个的区别吧。刷面试题的朋友肯定能说出来String声明的对象是不可变对象,其他两个类声明的对象是可变的对象。
那String怎么就是不可变的了呢?
让我们来看看String类的源码吧。
String类的源码
可以看到String类是通过内部的一个char数组实现的。类和类内的属性都是用final修饰的。
看过我前面写的《理解java的final、finally以及finalize》这篇文章,就会知道用final修饰的的变量在首次赋值后是不能被修改的。所以String类声明的对象就是不可变的了。
我们还来打个比方。
通过“String 印刷匠张三”这样声明的变量,这个印刷匠张三使用的技术比较古老,是通过雕版印刷来实现的。
当我们提出一个需求“印刷匠张三="大吉大利"”时,印刷匠张三会去雕刻一张新版,内容是“大吉大利”。
而当我们又提出一个需求“印刷匠张三="今晚吃鸡"”时,刚才雕刻的雕版就不能用了,印刷匠张三会再去雕刻一张新版(新建对象),内容是“今晚吃鸡”。
而StringBuffer和StringBuilder就不一样了,他们使用了比较新的技术,活字印刷。
拿StringBuffer举例来说。
遇到“StringBuffer 印刷匠李四=new StringBuffer("大吉大利")”这样的需求时,这个印刷匠李四会组合好“大吉大利”的内容提供出来。
而当遇到“ 印刷匠李四= 印刷匠李四.append("今晚吃鸡")”这样的需求时,印刷匠李四不是重新去雕版(不用新建对象),而是在原来的基础上继续拼装“今晚吃鸡”。
通过这个例子应该好理解多了吧。
02StringBuffer和StringBuilder的区别
通过百度能搜索到好多好多说她们两个区别的文章。
看过的朋友应该都知道了StringBuffer是线程安全的,而StringBuilder不是线程安全的。
那为什么是这样的呢。那是因为在StringBuffer的方法上使用synchronized做了修饰。用synchronized修饰的方法都必须同步访问。
打一个比方有一个食堂(相对于被synchronized修饰的方法),这个食堂用synchronized做了修饰。这样这个食堂同时只能让一个人吃饭。
每个顾客要来吃饭,要先验证一下食堂有没有别人在用,如果没有才可以进去吃。如果食堂有人在用,那必须要等在用的人用完,才可以进去吃饭。
那StringBuilder为什么就不是线程安全的呢。
因为StringBuilder的方法没有用synchronized进行修饰。
我们还打个比方吧。
有一面墙上写了数字1,然后由两个人(两个线程)同时去修改数字,修改的改则是将墙上的数字擦去后并加1写到墙上。
如果是按照synchronized修饰的效果的话,两个人(线程)是不可以同时去重写墙上的数字的,只能轮流来,最后墙上的数字会是3。
但是如果不用synchronized修饰的话,则能同时去改。这样就有可能会有两个人同时看到墙上是1,然后都去把墙上数擦掉,然后写2。
这样的结果就是不正确的了。
所以StringBuilder不是线程安全的。
但是如果不存在多线程调用的情况时,因为StringBuilder是不需要做调用方法前的同步处理的,所以执行效率是要高于StringBuffer的。
好了,今天就讲这些吧。