String,StringBuffer与StringBuilder的区别
字符串广泛应用 在Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。
需要注意的是,String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,这样不仅效率低下,而且大量浪费有限的内存空间。我们来看一下这张对String操作时内存变化的图:
我们可以看到,初始String值为“hello”,然后在这个字符串后面加上新的字符串“world”,这个过程是需要重新在栈堆内存中开辟内存空间的,最终得到了“hello world”字符串也相应的需要开辟内存空间,这样短短的两个字符串,却需要开辟三次内存空间,不得不说这是对内存空间的极大浪费。为了应对经常性的字符串相关的操作,谷歌引入了两个新的类——StringBuffer类和StringBuild类来对此种变化字符串进行处理。
当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。
和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够**被多次的修改,并且不产生新的未使用对象。**因为对这2个类进行修改都是在本身存在的那个对象上进行的。
StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。
三者的继承结构:
String是常量
StringBuffer与StringBuilder是变量
StringBuffer线程安全,速度慢
StringBuilder线程不安全,速度快。
使用情境:
(1)如果要操作少量的数据用 String;
(2)多线程操作字符串缓冲区下操作大量数据 StringBuffer;
(3)单线程操作字符串缓冲区下操作大量数据 StringBuilder。
Java.lang.StringBuffer线程安全的可变字符序列。
可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append(“le”) 会使字符串缓冲区包含“startle”,而 z.insert(4, “le”) 将更改字符串缓冲区,使之包含“starlet”。
在大部分情况下 StringBuilder > StringBuffer
很显然,String和StringBuffer中的value[]都用于存储字符序列。但是,
(1) String中的是常量(final)数组,只能被赋值一次。
比如:new String(“abc”)使得value[]={‘a’,‘b’,‘c’}(查看jdk String 就是这么实现的),之后这个String对象中的value[]再也不能改变了。这也正是大家常说的,String是不可变的原因 。
注意:这个对初学者来说有个误区,有人说String str1=new String(“abc”); str1=new String(“cba”);不是改变了字符串str1吗?那么你有必要先搞懂对象引用和对象本身的区别。这里我简单的说明一下,对象本身指的是存放在堆空间中的该对象的实例数据(非静态非常量字段)。而对象引用指的是堆中对象本身所存放的地址,一般方法区和Java栈中存储的都是对象引用,而非对象本身的数据。
(2) StringBuffer中的value[]就是一个很普通的数组,而且可以通过append()方法将新字符串加入value[]末尾。这样也就改变了value[]的内容和大小了。
比如:new StringBuffer(“abc”)使得value[]={‘a’,‘b’,‘c’,’’,’’…}(注意构造的长度是str.length()+16)。如果再将这个对象append(“abc”),那么这个对象中的value[]={‘a’,‘b’,‘c’,‘a’,‘b’,‘c’,’’…}。这也就是为什么大家说 StringBuffer是可变字符串 的涵义了。从这一点也可以看出,StringBuffer中的value[]完全可以作为字符串的缓冲区功能。其累加性能是很不错的,在后面我们会进行比较。
总结,讨论String和StringBuffer可不可变。本质上是指对象中的value[]字符数组可不可变,而不是对象引用可不可变。
java.lang.StringBuilder一个可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。
StringBuffer和StringBuilder可以算是双胞胎了,这两者的方法没有很大区别。但在线程安全性方面,StringBuffer允许多线程进行字符操作。这是因为在源代码中StringBuffer的很多方法都被关键字synchronized 修饰了,而StringBuilder没有。