版权声明:本文为博主原创文章,转载请注明作者和出处。 https://blog.csdn.net/xinqing5130/article/details/83107132
String对象是immutable不可变对象
StringBuffer和StringBuilder是可变的,为什么,他们又是如何实现的?
这里以StringBuilder为例,因为StringBuffer和StringBuilder大体是相同的,只是线程安全的差别以及由此产生的效率差别。
StringBuilder继承了AbstractStringBuilder,并实现了Serializable和charSequance接口
public final class StringBuilder extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
我们创建一个StringBuilder对象,并执行append方法的时候,它会执行AbstractStringBuilder的append方法
StringBuilder sb= new StringBuilder();
sb.append("xxx");
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
下面是父类的append方法:在父类方法里,它需要判断是否扩容,具体在ensureCapacityInternal()方法里
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
点进去,如果需要,则扩容,具体在expandCapacity方法里
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
}
再点进去,我们会发现它默认扩容的大小是value.length*2+2
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);
}
在这个方法的最后,有一行代码
value = Arrays.copyOf(value, newCapacity);
进入之后会发现,它重新建一个char类型数组,因为同样数组大小定义了是不能再变的,只能新建
新建数组后进行数组复制,然后return这个新的数组
public static char[] copyOf(char[] original, int newLength) {
char[] copy = new char[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
最后再回到expandCapacity()方法,value指向新的char类型数组(最后一行),实现字符串扩充。
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);
}
StringBuffer和StringBuilder相比,只是方法加了synchronized关键字修饰,因此是线程安全的。
但是效率要比后者低。
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}