[面试题]String、StringBuffer、StringBuilder 有什么区别?
这是一道经典的面试题,我在一些面试题目的文章中都能看到,所以希望在此总结一下。
先说结论
线程安全性
-
线程安全:String、StringBuffer
-
非线程安全:StringBuilder
执行效率
- StringBuilder>StringBuffer>String
存储空间
-
String 的值不可变,每次对 String 的操作都会生成新的 String 对象,耗费大量内存空间,从而引起 GC
-
StringBuffer 和 StringBuilder 都是可变的
使用场景
-
操作少量的数据用 String
-
单线程操作大量数据用 StringBuilder
-
多线程操作大量数据用 StringBuffer
以上内容来源于[程序汪公众号]
如果只是针对面试题,那上面这些答案应该已经足够了,但是我想深入研究一下这里面的细节,希望可以对你我都有所帮助。
String 类
什么是 String 类?
-
String 类是典型的 Immutable 类,其自身声明为 final class,代表它的不可继承。
-
String 类本质上是个 char 数组,而且用 private 和 final 关键字修饰。为了避免我们通过对数组的操作或者更粗暴的反射直接修改数组,String 的所有方法都没有去动数组里的元素。
由于它的不可变性,类似拼接、裁剪字符串等动作,都会产生新的 String 队形。String 操作的效率往往对应用性能有明显影响。
String 类的特性是什么?
-
由于 String 类的不可变性,所以说 String 类是线程安全的
-
也由于 String 类的不可变性,每次对 String 类的操作都会产生新的 String 对象,耗费大量空间,影响效率
StringBuffer 类
什么是 StringBuffer 类?
-
为了解决 String 类拼接产生太多中间对象的问题,所以在 Java 1.5 版本中增加了 StringBuffer 类
-
可以通过 StringBuffer 类的 append 或者 add 方法,把字符创添加到已有序列的末尾或者指定位置
StringBuffer 类的特性是什么?
-
StringBuffer 是线程按成的可修改字符序列,因为 append 方法都用 synchronized 关键字修饰
-
也由于它的线程安全,带来了额外的性能开销
除非有线程安全的需要,不然还是使用它的继承者,也就是 StringBuilder
----在极客时间的 Java 核心技术 36 讲栏目中是这样定性的
StringBuilder 类
什么是 StringBuilder 类?
- StringBuilder 类在能力上和 StringBuffer 没有本质区别,但是它去掉了线程安全的部分,有效减少了开销
StringBuilder 类的特性是什么?
-
StringBuilder 是非线程安全的
-
因为减少了开销,所以它的执行效率也最高
StringBuilder 类是绝大部分情况下进行字符串拼接的首选
----同样在极客时间的 Java 核心技术 36 讲栏目中这样提到
题外话
-
StringBuffer 类和 StringBuilder 类的初始数组大小是 16,至于为什么是 16 在这里不作讨论
-
可能有人会说我一直都是 String 一路走到黑,也不见有什么问题啊,关于这个问题我们可以通过下面的代码解释,若果我们通过 JDK8 编译再反编译的话,可以看到,字符串拼接操作会自动被 javac 转换为 StringBuilder 操作。而在 JDK 9 里面则是因为 Java 9 为了更加统一字符串操作优化,提供了 StringConcatFactory,作为一个统一的入口。
String myStr = "aa" + "bb" + "cc" + "dd";
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于