StringBuilder,StringBuffer 相对于String来说可以被多次修改而不会产生新的对象,而StringBuilder与StringBuffer最大的不同就是在于StringBuilder的方法不是线程安全的(不能同步访问)。我们以StringBuilder为例:
StringBuilder可以被多次修改而不会产生新的对象可以从源码分析为什么:
StringBuilder对于变量的修改主要用了方法append(String),以append方法为例来分析:而StringBuilder继承了 AbstractStringBuilder类实现了Serializable, CharSequence,此append方法调用了父类AbstractStringBuilder的appendappend(String paramString)方法,该方法如下所示:
public AbstractStringBuilder append(StringparamString)
{
if (paramString == null) {
paramString = "null";
}
int i = paramString.length();
if (i == 0) {
return this;
}
int j = this.count + i;
if (j > this.value.length) {
expandCapacity(j);
}
paramString.getChars(0, i, this.value,this.count);
this.count = j;
return this;
}
分析代码可以得到当传入的paramString为空的时候直接返回原来的值,如果不为null则获取this.count+ paramString.length()也就是合并的总长度,在判断是否大于以前this字符串的长度,大于调用expandCapacity(j)方法如下:
void expandCapacity(int paramInt)
{
int i = (this.value.length + 1) * 2;
if (i < 0) {
i = 2147483647;
} else if (paramInt > i) {
i = paramInt;
}
this.value = Arrays.copyOf(this.value, i);
}
定义int变量i并赋值为原来字符长度2倍+2,如果长度小于0则将i赋值为int的最大值2^31-1,如果不小于0(一般都不小于0)合并总长度大于原来字符长度+2的话则将i的值变为合并的总长度值,最后调用Arrays.copyOf复制数组并扩建字符数组的长度为i,并赋值赋值给以前的字符串this;此方法的目的就是对以前字符数组进行扩容以此有足够的空间来添加新的字符串且不改变原来的对象还是this
接着看上面的append方法调用paramString.getChars(0, i, this.value, this.count)而此方法源码如下:
public void getChars(int paramInt1, intparamInt2, char[] paramArrayOfChar, int paramInt3)
{
if (paramInt1 < 0) {
throw newStringIndexOutOfBoundsException(paramInt1);
}
if ((paramInt2 < 0) || (paramInt2 >this.count)) {
throw newStringIndexOutOfBoundsException(paramInt2);
}
if (paramInt1 > paramInt2) {
throw newStringIndexOutOfBoundsException("srcBegin > srcEnd");
}
System.arraycopy(this.value, paramInt1,paramArrayOfChar, paramInt3, paramInt2 - paramInt1);
}
其实就是实现了一个System.arraycopy(src,srcPos, dest, destPos, length)方法,而System.arraycopy其实是java的一个调用别的语言的本地接口,它会实现元对象src截取从srcPos位置开始到srcPos+length长度这段对象内容复制到目标对象dest从dest的放置位置destPos开始赋值的一个复制方法,它也可以自己对自己进行复制赋值,
这是对象内容修改而不改变的关键,我们分析传进来的参数
this.value就是paramString.value(是paramString调用的getChars方法此处的this不同上面的this.value)
paramInt1源对象要复制的起始位置为0
paramArrayOfChar为以前的对象this.value(this.value千万别搞混了)
paramInt3以前对象this的长度count
paramInt2 - paramInt1(也就是i)以前对象this放置的起始位置为i从this的末尾开始
根据上面的参数来看次方发就是将要append的String对象paramString复制并拼接赋值到扩容后的源this对象以此来实现修改对象的append操作并不改变原来的对象