今天用StringBulider的时候被坑到了,想着它的构造和append方法一样可以传一个int型的变量进去:于是写下了大概这样的代码:
int i= 1;
StringBuilder sb = new StringBuilder(i);
用的在线编译器也没报错就是结果怎么也不对。调了半天才发现如果传入一个int值则代表初始化长度。。。那句话其实应该这样写
StringBuilder sb = new StringBuilder(""+i);
点进它的构造函数发现无参的默认长度是16有参的调用AbstractStringBuilder类的构造。
public StringBuilder(int capacity) {
super(capacity);
}
AbstractStringBuilder该类实现了Appendable, CharSequence接口。
有参的构造其实就是建立了一个长度为capacity的数组
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
最大长度是int的最大值-8
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
观察连接以及扩容方式以String类型为例:
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;
}
如果str为null,则append ‘n’,‘u’,‘l’,'l’四个字母
否则检查是否进行扩容只要需要的长度大于数组的长度就进行扩容
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
扩容方式如果2倍+2大于所需长度则2倍+2,否则新长度为所需长度。如果太长超过最大值的话在 hugeCapacity里又分了两种情况超过int的最大值抛出栈溢出异常否则返回StringBuilder的最大长度。
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;
}
现在我们的value是一个足够append(str)的数组,我们再将str的值一一赋在原先值后面即可。
str.getChars(0, len, value, count);
相似的如果参数是一个char[] str,将str从0号下标开始赋值至value的count下标之后len个长度。
System.arraycopy(str, 0, value, count, len);