Java StringBuffer类用法详解
前面介绍了 String 类的使用,在实际开发中使用 String 类会存在一个问题,String 对象一旦创建,其值是不能修改的,如果要修改,会重新开辟内存空间来存储修改之后的对象,即修改了 String 的引用。
理由很简单,String 的底层是用数组来存值的,数组长度不可改变这一特性导致了上述问题,所以如果开发中需要对某个字符串进行频繁的修改,使用 String 就不合适了,会造成内存空间的浪费。
如何解决这个问题呢?可以使用 StringBuffer 类来解决。
StringBuffer 和 String 类似,底层也是用一个数组来存储字符串的值,并且数组的默认长度为 16,即一个空的 StringBuffer 对象,数组长度为 16:
当我们调用有参构造创建一个 StringBuffer 对象时,数组长度就不是 16了,而是根据当前对象的值来决定数组的长度,“值的长度+16”作为数组的长度:
所以一个 StringBuffer 创建完成之后,有 16 字节的空间可以对其值进行修改。如果修改的值范围超出了 16 字节,则调用 ensureCapacityInternal() 方法继续对底层数组进行扩容,并且保持引用不变,ensureCapacityInternal()方法的具体实现如下:
以上就是 StringBuffer 创建及修改的底层原理。接下来,我们来通过代码完成对 StringBuffer 的使用,StringBuffer 常用方法如下表所示。
举个简单的例子:
理由很简单,String 的底层是用数组来存值的,数组长度不可改变这一特性导致了上述问题,所以如果开发中需要对某个字符串进行频繁的修改,使用 String 就不合适了,会造成内存空间的浪费。
如何解决这个问题呢?可以使用 StringBuffer 类来解决。
StringBuffer 和 String 类似,底层也是用一个数组来存储字符串的值,并且数组的默认长度为 16,即一个空的 StringBuffer 对象,数组长度为 16:
@HotSpotIntrinsicCandidate public StringBuffer{ super(16); }
当我们调用有参构造创建一个 StringBuffer 对象时,数组长度就不是 16了,而是根据当前对象的值来决定数组的长度,“值的长度+16”作为数组的长度:
@HotSpotIntrinsicCandidate public StringBuffer(String s){ super(str.length()+16); append(str); }
所以一个 StringBuffer 创建完成之后,有 16 字节的空间可以对其值进行修改。如果修改的值范围超出了 16 字节,则调用 ensureCapacityInternal() 方法继续对底层数组进行扩容,并且保持引用不变,ensureCapacityInternal()方法的具体实现如下:
private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code int oldCapacity = value.length >> coder; if (minimumCapacity - oldCapacity > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity) << coder); } }
以上就是 StringBuffer 创建及修改的底层原理。接下来,我们来通过代码完成对 StringBuffer 的使用,StringBuffer 常用方法如下表所示。
方法 | 描述 |
---|---|
public StringBuffer() | 无参构造,创建一个空的StringBuffer |
public StringBuffer(String str) | 有参构造 |
public synchronized int length() | 返回 StringBuffer 的长度 |
public synchronized char charAt(int index) | 返回字符串中指定位置的字符 |
public synchronized StringBuffer append(String str) | 追加字符 |
public synchronized StringBuffer delete(int start, int end) | 删除指定区间内的字符 |
public synchronized StringBuffer deleteCharAt(int index) | 删除指定位置的字符 |
public synchronized StringBuffer replace(int start, int end, String str) | 将指定区间内的值替换为 str |
public synchronized String substring(int start) | 裁取字符串从指定位責开始到结尾 |
public synchronized String substring(int start, int end) | 截取字符串从指定位置开始到指定位置结束 |
public synchronized StringBuffer insert(int offset, String str) | 向指定位置插入 str |
public int indexOf(String str) | 从头开始童找指定字符的位直 |
public int indexOf(String str, int fromlndex) | 从指定的位置开始查找指定字符的位置 |
public synchronized StringBuffer reverse() | 进行反转 |
public synchronized String toString() | 返回 StringBuffer 对应的 String |
举个简单的例子:
public class StringBufferTest { public static void main(String[] args) { StringBuffer stringBuffer = new StringBuffer(); System.out.println("StringBuffer:"+stringBuffer); System.out.println("StringBuffer的长度:"+stringBuffer.length()); stringBuffer = new StringBuffer("Hello World"); System.out.println("StringBuffer:"+stringBuffer); System.out.println("下标为2的字符是:"+stringBuffer.charAt(2)); stringBuffer = stringBuffer.append("Java"); System.out.println("append之后的StringBuffer:"+stringBuffer); stringBuffer = stringBuffer.delete(3, 6); System.out.println("delete之后的StringBuffer:"+stringBuffer); stringBuffer = stringBuffer.deleteCharAt(3); System.out.println("deleteCharAt之后的StringBuffer:"+stringBuffer); stringBuffer = stringBuffer.replace(2,3,"StringBuffer"); System.out.println("replace之后的StringBuffer:"+stringBuffer); String str = stringBuffer.substring(2); System.out.println("substring之后的String:"+str); str = stringBuffer.substring(2,8); System.out.println("substring之后的String:"+str); stringBuffer = stringBuffer.insert(6,"six"); System.out.println("insert之后的StringBuffer:"+stringBuffer); System.out.println("e的下标是:"+stringBuffer.indexOf("e")); System.out.println("下标6之后的e的下标是:"+stringBuffer.indexOf("e",6)); stringBuffer = stringBuffer.reverse(); System.out.println("reverse之后的StringBuffer:"+stringBuffer); str = stringBuffer.toString(); System.out.println("StringBuffer对应的String:"+str); } }运行结果为:
StringBuffer:
StringBuffer的长度:0
StringBuffer:Hello World
下标为2的字符是:l
append之后的StringBuffer:Hello WorldJava
delete之后的StringBuffer:HelWorldJava
deleteCharAt之后的StringBuffer:Helorldjava
replace之后的StringBuffer:HeStringBufferorldJava
substring之后的String:StringBufferorldJava
substring之后的String:String
insert之后的StringBuffer:HeStrisixngBufferorldJava
e的下标是:1
下标6之后的e的下标是:15
reverse之后的StringBuffer:avaJdlroreffuBgnxisirtSeH
StringBuffer对应的String:avaJdlroreffuBgnxisirtSeH