一、概述
可以通过length()方法获取StringBuffer对象中存放的字符串长度
可以通过capacity()方法来获取StringBuffer对象的实际容量
StringBuffer三种参数类型
1.StringBuffer()的初始容量可以容纳16个字符,当StringBuffer实例对象存放的字符长度大于16时,实例对象容量就自动增加。
2.StringBuffer(int size)可以指定分配给实例对象的初始容量,参数为size指定的字符个数。当该实例对象存放的字符串长度大于size个字符时,实例对象的容量就自动增加。
3.StringBuffer(String s)可以指定给实例对象的初始容量为16个字符加上参数字符串s的长度。当该实例对象存放的字符串长度大于size个字符时,实例对象的容量自动增加。
二、代码演示
public class StringBuffertest {
public static void main(String[] args) {
/*1、StringBuffer无参构造对象容量*/
/*1.1 输出StringBuffer无参构造对象未添加数据时的初始容量*/
StringBuffer sb1=new StringBuffer();
System.out.println("1.1 无参构造的初始容量:"+sb1.capacity());
//输出:1.1 无参构造的初始容量:16
/*查看添加数据后,StringBuffer无参构造对象的容量*/
sb1.append("aaa1");
sb1.append("bbb2");
sb1.append("ccc3");
sb1.append("ddd4");
System.out.println("**sb1录入的数据:\t"+sb1);
//输出:**sb1录入的数据: aaa1bbb2ccc3ddd4
System.out.println("1.2 无参构造对象sb1添加初始容量大小的数据内容后 容量:"+sb1.capacity()+"\tsb1对象内数据实际长度:"+sb1.length());
//输出:1.2 无参构造对象sb1添加初始容量大小的数据内容后 容量:16 sb1对象内数据实际长度:16
/*查看再插入数据后 StringBuffer扩容效果*/
sb1.append("e");
System.out.println("**添加数据后的sb1:\t"+sb1);
//**添加数据后的sb1: aaa1bbb2ccc3ddd4e
System.out.println("1.3 无参构造对象sb1插入数据后 容量:"+sb1.capacity()+"\tsb1对象内数据实际长度:"+sb1.length());
//1.3 无参构造对象sb1插入数据后 容量:34 sb1对象内数据实际长度:17
/*2、StringBuffer有参构造对象容量-size指定长度*/
/*2.1 输出StringBuffer有参构造(size指定长度)的容量*/
StringBuffer sb2=new StringBuffer(3);
System.out.println("2.1 有参构造(size指定长度)的容量:"+sb2.capacity());
//2.1 有参构造(size指定长度)的容量:3
/*2.2 查看有参(size指定长度)构造对象sb2添加数据后的容量变化*/
/*添加字符数(4个)超过临界点(3)*/
sb2.append("hhh1");
System.out.println("**添加数据后的sb2:\t"+sb2);
//输出:**添加数据后的sb2: hhh1
System.out.println("2.2 有参(size指定长度)构造对象sb2添加初始容量大小的数据内容后 容量:"+sb2.capacity()+"\tsb2对象内数据实际长度:"+sb2.length());
//输出:2.2 有参构造对象sb2添加初始容量大小的数据内容后 容量:8 sb2对象内数据实际长度:4
/*2.3 查看有参(size指定长度)构造对象sb2再次扩容的容量变化*/
/*添加字符数(5个)超过临界点(8)*/
sb2.append("jjj1k");
System.out.println("**再次添加数据后的sb2:\t"+sb2);
//输出:**再次添加数据后的sb2: hhh1jjj1k
System.out.println("2.3 有参(size指定长度)构造对象sb2再次扩容后 容量:"+sb2.capacity()+"\t sb2对象内数据实际长度:"+sb2.length());
//输出:2.3 有参(size指定长度)构造对象sb2再次扩容后 容量:18 sb2对象内数据实际长度:9
/*2.4 查看有参(size指定长度)构造对象sb2_1扩容超过一次扩容所得容量的容量变化*/
StringBuffer sb2_1=new StringBuffer(3);
sb2_1.append("ooo");
/*添加字符数(7个)超过临界点(8)*/
sb2_1.append("ppp1sss");
System.out.println("**再次添加数据后的sb2_1:\t"+sb2_1);
//输出:**再次添加数据后的sb2_1: oooppp1sss
System.out.println("2.4 有参(size指定长度)构造对象sb2_1扩容后 容量:"+sb2_1.capacity()+"\tsb2_1对象内数据实际长度:"+sb2_1.length());
//输出:2.4 有参(size指定长度)构造对象sb2_1再次扩容后 容量:10 sb2_1对象内数据实际长度:10
/*3、StringBuffer有参构造对象容量-参数指定长度*/
/*3.1 输出StringBuffer有参构造(参数指定长度)的容量*/
StringBuffer sb3=new StringBuffer("zzz");
System.out.println("3.1 有参构造(参数指定长度)的容量:"+sb3.capacity());
//3.1 有参构造(参数指定长度)的容量:19
/*3.2 查看有参(参数指定长度)构造对象sb3添加数据后的容量变化*/
/*添加字符数(17个)超过临界点*/
sb3.append("1xxx2yyy3www4vvv5");
System.out.println("**添加数据后的sb3:\t"+sb3);
//输出:**添加数据后的sb3: zzz1xxx2yyy3www4vvv5
System.out.println("3.2 有参(参数指定长度)构造对象sb3添加初始容量大小的数据内容后 容量:"+sb3.capacity()+"\t sb3对象内数据实际长度:"+sb3.length());
//输出:3.2 有参(参数指定长度)构造对象sb3添加初始容量大小的数据内容后 容量:40 sb3对象内数据实际长度:20
/*4、有参与无参相加*/
/*4.1 无参构造对象sb1加到有参构造对象sb3上,此时sb1无变化*/
sb3.append(sb1);
System.out.println("**添加sb1后的sb3:\t"+sb3);
//输出:**添加sb0后的sb3: zzz1xxx2yyy3www4vvv5aaa1bbb2ccc3ddd4e
System.out.println("4.1 有参构造对象sb3添加无参构造对象的数据内容后 容量:"+sb3.capacity()+"\t sb3对象内数据实际长度:"+sb3.length());
//输出:4.1 有参构造对象sb3添加无参构造对象的数据内容后 容量:40 sb3对象内数据实际长度:37
/*4.2 有参构造对象sb3加到无参构造对象sb1上*/
sb1.append(sb3);
System.out.println("**添加sb3后的sb1:\t"+sb1);
//输出:**添加sb3后的sb1: aaa1bbb2ccc3ddd4ezzz1xxx2yyy3www4vvv5aaa1bbb2ccc3ddd4e
System.out.println("4.2 无参构造对象sb1添加有参构造对象的数据内容后 容量:"+sb1.capacity()+"\tsb0对象内数据实际长度:"+sb1.length());
//输出:4.2 无参构造对象sb1添加有参构造对象的数据内容后 容量:70 sb1对象内数据实际长度:54
}
三、例子分析
1.无参扩容
当超过初始容量16时:新容量=初始容量2+2;
如1.3: 34=162+2
2.有参扩容
当超过初始容量16+(指定长度)时:新容量=初始容量2+2;
如2.2: 8=32+2;
当超过初始容量16+(字符串长度)时:新容量=初始容量2+2;
如3.2: 40=192+2;
3.有参与无参结合
以赋值对象为基础,当超过赋值对象初始容量时:新容量=初始容量2+2;
如4.1: 40=192+2;
如4.2: 70=34*2+2;
4.再次扩容
以第一次扩容后的容量为基础:第二次扩容的新容量=第一次扩容的容量2+2;
如2.3: 18=82+2。
5.添加超过一次扩容容量的字符串
扩容后仍不够存储字符串,则取新的字符串的长度为新的容量。
新容量=组合后新的字符串长度;
如2.4: 10=10 (3*2+2=8<10);
不论各种情况,以要改变的对象实例的容量为基础,检测扩容后长度合适后进行扩容,或者以新组合的超出扩容范围的字符串长度为准。
四、源代码分析
源码调用父类抽象类AbstractStringBuilder类来进行初始化:
初始化容量为16。
初始化容量为默认值(16)+字符串参数长度。
用append()方法进行扩容:
实例对象增加的长度如果超过了容量就需要进行扩容:构建新的存储空间,将原来的复制过去。
append添加字符串的时候,先计算添加后字符串大小,传入ensureCapacityInternal 方法,进行是否扩容的判断。
需要扩容就调用expandCapacity方法进行扩容:
尝试将新容量扩为大小变成2倍+2 if 判断一下 容量如果不够,直接扩充到需要的容量大小。