可变性
StringBuilder与StringBuffer都继承自AbstractStringBuilder抽象类,说明线程安全不安全都是在继承之后实现的。在AbstractStringBuilder中维护一个数组,但是不同于String类中,代码如下:
/* The value is used for character storage. */
char[] value;
String类中为
/** The value is used for character storage. */
private final char value[];
- 使用final关键字修饰后,即创建对象后 ,value指向的地址不能再改变。
- 同时,String内中也没有提供改变value[]数组中值得方法,因此不可变。
- 但是在StringBuffer与StringBuilder中维护的char[] value,没有final修饰,同时,类中还有改变值得方法,因此,可变。
核心方法
append方法
调用StringBuilder,使用较多的方法,主要是向创建的StringBuilder中添加元素。 针对不同的输入情况,重载了许多append方法,根据使用情况自己调用就行。
容量扩展expandCapacity(int minimumCapacity)
在StringBuilder中,也涉及到动态扩容,这里的扩容不同于ArrayList中的扩容。StringBuilder初始化时,可以直接设定容量,设定值,即为在类中创建数组的容量大小。不设定,默认的容量为16测试代码如下:
public static void main(String[] args) {
// 容量
StringBuilder sb1 = new StringBuilder(12);
System.out.println(sb1.capacity()); // 12
StringBuilder sb2 = new StringBuilder(20);
System.out.println(sb2.capacity()); // 20
StringBuilder sb3 = new StringBuilder();
System.out.println(sb3.capacity()); // 16
}
当数组容量超出初始容量时,再添加元素,会进行扩容。当添加元素的个数加上已经存在的元素个数大于当前容量时,会调用expandCapacity()方法,进行扩容。源码如下:
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0)
newCapacity = minimumCapacity;
if (newCapacity < 0) {
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
value = Arrays.copyOf(value, newCapacity);
}
// 测试
public static void main(String[] args) {
// 容量
StringBuilder sb1 = new StringBuilder(12);
System.out.println(sb1.capacity()); // 12
for(int i = 0; i < 12; i++)
{
sb1.append(i);
}
System.out.println(sb1.capacity()); // 26 (12 * 2 + 2)
}
- 新的容量,直接将原来容量扩大两倍再加上2
因此26 = 12 * 2 + 2
至于为什么采用这样的方式,还不明白。 - 在Arrays.copyOf()方法里,将旧数组copy至新容量的新数组,是又创建了一个新的数组。因为数组容量一旦设定,是不能再改变的。
StringBuilder与StringBuffer比较
-
线程安全
StringBuilder线程不安全,StringBuffer线程安全, 若多线程使用,涉及到线程安全使用StringBuffer。 -
执行效率问题
StringBuilder > StringBuffer > String StringBuilder与StringBuffer类似,StringBuffer确保了安全,效率相比StringBuilder低。
对于String对象,进行多次添加,会创建多个对象,因此效率会相对低。
但以上分析也不绝对,因为添加次数的多少及方式,也会影响结果,所以仅供参考
StringBuilder与String
- StringBuilder可变
StringBuilder类中,维护了一个char value[],为默认修饰符的数组,能被子类访问,或者子类与父类在同一个包下可以访问。但是StringBuilder类,使用了final修饰,不可被继承。在StringBuilder内部,提供了修改数组value[]值的方法,所以StringBuilder可变。
- String不可变
String类中,维护一个使用private,final修饰的数组value[],因此是私有的,不可变的,同时String类中也没有提供修改数组value[]的方法,因此,不可变。
具体String类相关可参考:String类源码解析