StringBuffer&StringBuilder
1 StringBuffer和StringBuilder是什么
与String
类一样,StringBuffer
和StringBuilder
也是表示字符串的类。
String
vs StringBuffer
和StringBuilder
:
1) 相同点:
- 三者都是表示字符串的类;
- 三者在底层都是用
char
型数组来表示字符串的值。具体地,String
类是有一个私有char
型数组属性value
来表示字符串的值;StringBuffer
和StringBuilder
是都继承于一个抽象类AbstractStringBuilder
,继承了该抽象类中的char
型数组属性value
来表示字符串的值。
2) 不同点:
String
是表示不变的字符串;而StringBuffer
和StringBuilder
是表示可变的字符串,从源码上看对应的表示字符串值的value
属性也是前者是final
的,后者并不是。
String
与StringBuffer
和StringBuilder
底层都是用char
型数组来表示字符串的值,但StringBuffer
和StringBuilder
是可变的字符串的源码分析:
String
中表示字符串值的属性value
是final
的,因此只要String
对象对应的字符串改变了,只能用以新字符串为value
的对应的新的String
对象来替换。因此,String
代表的是不可变字符串,一旦改变就是改变了对象。StringBuffer
和StringBuilder
中表示字符串值的属性value
不是final
的,因此即使其对应对象的字符串改变了,也只是对应对象其中的value
属性改变了,对应的对象并没有改变。StringBuffer
和StringBuilder
中表示字符串值的属性value
本身就是char
型数组,一个引用类型数据,其引用的数组(即value对应的地址值)也不是随着对应字符串改变就一定改变。因为在构造StringBuffer
和StringBuilder
对象时,其对应的char
型数组属性value
是具有容量capacity
的,也就是说,StringBuffer
和StringBuilder
对象对应的字符串的改变或者表示都是基于capacity
长度的char
型数组,只有当对应字符串因为改变超出了capacity
长度,才会导致对应value
属性引用的地址值改变。
具体源码分析如下,以StringBuffer
为例,在以下方面StringBuilder
与StringBuffer
没有区别:StringBuffer
有四个构造器:空参构造器、指定capacity
的构造器、指定字符串的构造器和指定CharSequence
(也理解为指定字符串)的构造器。
对于空参构造器public StringBuffer()
,它是构造一个表示空字符串的对应字符串对象,但是底层是具有16个字符长度的。
对于指定
capacity
的构造器public StringBuffer(int capacity)
,就是构造一个表示空字符串的对应字符串对象,但是底层对应字符数组长度为指定长度。
对于指定字符串的构造器
public StringBuffer(String str)
,是构造一个表示对应字符串的对应字符串对象,但是底层对应字符数组长度为16+指定字符串的长度。由于源码是用了str.length
来创建char
型数组,因此如果str
为null
,会产生空指针异常。
StringBuffer
的append
方法就是在底层char型数组中已有的字符后面加上新的字符或字符串,简单地说,就是利用底层char型数组还没被利用的容量。根据源码可知,当append
的新字符或字符串的长度与原有字符串长度之和超过底层char型数组的长度时,就会利用数组复制方法进行扩容,即开辟一个新的更大的char型数组并将新字符或字符串的长度与原有字符串一起复制过来,作为value
属性的新的地址值。
具体扩容的长度默认为原capacity
×2+2。
StringBuffer
vs StringBuilder
:String
和StringBuffer
都是JDK1.0就存在的,StringBuilder
是JDK5新增的。StringBuffer
与StringBuilder
是相同的,区别在于,StringBuffer
是安全的,其所有方法都具有同步机制,而StringBuilder
是专为单线程设计的,不安全的,可以理解为StringBuffer
的无同步机制版本。因此,StringBuilder
相比于`StringBuffer效率更高。
总的来说,StringBuffer
和StringBuilder
都是表示可变字符串的,它们底层用了具有一定长度的char型数组并配合count
属性(表示有效字符的属性)来表示字符串,方法都是继承自抽象类AbstractStringBuilder
,StringBuffer
具有同步机制,而StringBuilder
没有。
由于StringBuffer
和StringBuilder
就是用来表示可变字符串的,并且字符串改变引起的扩容会影响效率,因此在使用时,推荐用能够指定capacity
的构造器来构造对应的对象来使用。
对于String
和StringBuffer
和StringBuilder
的效率是以此递增的,String
效率最低,因为每次改变都要重新创建新的对应对象。
2 StringBuffer和StringBuilder的方法
以StringBuffer
为例,StringBuilder
与其一样,区别仅在于有无同步机制。StringBuffer
对象表示的字符串本来就是可变的,这些方法中,有些方法之所以返回类型也为StringBuffer
,实际上其源码返回的就是this
。
public StringBuffer append(type argument)
:该方法就是在对应StringBuffer
对象表示的字符串的末尾加上指定的参数对应的字符串。该方法的参数适用于int、long、float、double、char、boolean、char[]、String、StringBuffer、Object
,原理实际上就是将对应参数对应的toString
的结果加到对应StringBuffer
对象表示的字符串的末尾。
参数为char[]
时,也可以同时指定将数组中哪个位置开始的、长度为多少的字符加到对应StringBuffer
对象表示的字符串的末尾。
注意,如果参数为null
时,append
方法将会把字符串"null"四个字符加进对应StringBuffer
对象表示的字符串的末尾。public StringBuffer insert(int offset, type argument)
:该方法就是在对应StringBuffer
对象表示的字符串中的指定索引位置插入指定的参数对应的字符串。该方法的适用参数与append()
方法相同,原理也类似。所有重载方法中的第一个参数都是指定对应StringBuffer
对象表示的字符串中的插入索引位置,第二个参数一般为要插入的对象。
参数为char[]
时,也可以同时指定将数组中哪个位置开始的、长度为多少的字符插入到对应StringBuffer
对象表示的字符串的指定索引位置。
注意,如果参数为null
时,insert
方法将会把字符串"null"四个字符加进对应StringBuffer
对象表示的字符串的末尾。public StringBuffer appendCodePoint(int codePoint)
:该方法将指定的Unicode码对应的字符加到对应StringBuffer
对象表示的字符串的末尾。
public int capacity()
:该方法返回对应StringBuffer
对象的容量。public int length()
:该方法返回对应StringBuffer
对象表示的字符串的长度。public char charAt(int index)
:该方法返回对应StringBuffer
对象表示的字符串中指定索引位置的字符。public StringBuffer delete(int start, int end)
:该方法删除对应StringBuffer
对象表示的字符串中指定开始到结尾位置的字符,左闭右开。public StringBuffer deleteCharAt(int index)
:该方法删除对应StringBuffer
对象表示的字符串中指定索引位置的字符。public void ensureCapacity(int minimumCapacity)
:该方法确保对应StringBuffer
对象的容量不小于指定的容量,如果小于,则会扩容,扩容后的容量大小要么为指定的容量,要么为当前StringBuffer
对象的容量的两倍加2。public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
:该方法将对应StringBuffer
对象表示的字符串中指定开始到结束位置的字符复制到指定的char型数组中,并指定指定的char型数组的复制开始位置。该方法不会改变指定char型数组的长度,等同于将指定char型数组的指定位置开始的字符替换为StringBuffer
对象表示的字符串中指定开始到结束位置的字符。public int indexOf(String str)
:该方法返回对应StringBuffer
对象表示的字符串中指定的字符串第一次出现的索引位置,如果没有出现,则返回-1。public StringBuffer replace(int start, int end, String str)
:该方法将用指定的字符串替换对应StringBuffer
对象表示的字符串中指定开始到结束位置的字符,左闭右开。该方法可以改变对应StringBuffer
对象表示的字符串的长度。该方法本质上是先删除掉指定字符串中指定开始到结束位置的字符,再插入指定的字符串。public StringBuffer reverse()
:该方法将对应StringBuffer
对象表示的字符串进行反转。public void setCharAt(int index, char ch)
:该方法将对应StringBuffer
对象表示的字符串中的指定索引位置的字符修改为指定字符。public void setLength(int newLength)
:该方法设置对应StringBuffer
对象表示的字符串的长度,如果新长度大于原长度,则多出的长度用字符代表null的字符填充,如果新长度小于原长度,则会截断字符串至新长度。public String substring(int start)
:该方法返回对应StringBuffer
对象表示的字符串从指定索引位置开始到最后的字符对应的字符串。public String substring(int start, int end)
:上个方法的指定结束位置的版本。public String toString()
:该方法返回对应StringBuffer
对象表示的字符串的String
版本。public void trimToSize()
:该方法会根据对应StringBuffer
对象表示的字符串的长度以及其对应的容量,来调整容量至当前字符串长度的容量。
注意示例: