String,StringBuffer,StringBuilder的继承关系图
String: 不可变字符序列,如果对原来的字符串进行改变,那么就会重新创建一个字符串对象并且指向该对象的地址,会消耗内存空间。
public static void main(String[] args) {
String str="123";
str+="456";
str+="789";
}
在用“+”来进行字符串的拼接的时候,会不断的创建新对象,且原来的对象依旧存在,造成了内存的浪费。
StringBuffer: 可变字符序列,效率较低,线程较安全。
StringBuilder: 可变字符序列,效率高,线程不安全。
源码分析:
StringBuffer中的方法中加了synchronized关键字,对方法加了同步锁,因此线程安全;但是加锁后,每次获取锁和释放锁都是需要一定的时间,因此效率会比StringBuffer慢一点。
StringBuilder、StringBuffer的缓冲区实现源码
初始容量默认为16,都是有缓冲区,且每次容量的增长都是 (当前容量*2)+2
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
// 此处将扩容后的字符数组赋值给原来的字符数组,从而实现缓冲区的扩容
}
}
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
private int hugeCapacity(int minCapacity) {
if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
throw new OutOfMemoryError();
}
return (minCapacity > MAX_ARRAY_SIZE)
? minCapacity : MAX_ARRAY_SIZE;
}