引言
StringBuffer和StringBuilder的构造方法各有四种构造方法,它们各自的构造方法总体原理上是一致的,细微之处有一个缓存区的置空操作。简单来讲可以把他们的构造方法理解成相同的。
构造方法
无参构造
/**
* Constructs a string buffer with no characters in it and an
* initial capacity of 16 characters.
*/
public StringBuffer() {
super(16);
}
/**
* Constructs a string builder with no characters in it and an
* initial capacity of 16 characters.
*/
public StringBuilder() {
super(16);
}
StringBuffer和StringBuilder的无参构造方法继承的是AbstractStringBuilder抽象类中的AbstractStringBuilder(int capacity)
方法。
/**
* Creates an AbstractStringBuilder of the specified capacity.
*/
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
AbstractStringBuilder(int capacity)
方法底层是一个默认容量为capacity=16
的字符数组,由此可以知道StringBuffer和StringBuilder无参构造方法构造出的对象的初始容量为16,可以用capacity()方法查看。
System.out.println(stringBuilder.capacity());
System.out.println(stringBuffer.capacity());
有参构造
① 自定义容量
构造一个容量自定义的StringBuffer或StringBuilder对象,传入int 类型的capacity自定义容量。
/**
* Constructs a string buffer with no characters in it and
* the specified initial capacity.
*
* @param capacity the initial capacity.
* @exception NegativeArraySizeException if the {@code capacity}
* argument is less than {@code 0}.
*/
public StringBuffer(int capacity) {
super(capacity);
}
/**
* Constructs a string builder with no characters in it and an
* initial capacity specified by the {@code capacity} argument.
*
* @param capacity the initial capacity.
* @throws NegativeArraySizeException if the {@code capacity}
* argument is less than {@code 0}.
*/
public StringBuilder(int capacity) {
super(capacity);
}
这个方法和无参构造走的都是AbstractStringBuilder(int capacity)
方法,和上面无参构造方法不同的是capacity参数,无参构造默认capacity=16
,而有参构造中capacity=capacity
(自定义的)
② 字符串定义容量
传入一个字符串str,使得capacity= str.length() + 16
,再调用append()方法进行处理。
/**
* Constructs a string buffer initialized to the contents of the
* specified string. The initial capacity of the string buffer is
* {@code 16} plus the length of the string argument.
*
* @param str the initial contents of the buffer.
*/
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
/**
* Constructs a string builder initialized to the contents of the
* specified string. The initial capacity of the string builder is
* {@code 16} plus the length of the string argument.
*
* @param str the initial contents of the buffer.
*/
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
Super()方法和上面两个是同一个方法,不同的是是StringBuffer方法中会把缓冲区进行置空操作toStringCache = null
,再走append()
方法。
/**
* Appends the specified string to this character sequence.
*
* The characters of the {@code String} argument are appended, in
* order, increasing the length of this sequence by the length of the
* argument. If {@code str} is {@code null}, then the four
* characters {@code "null"} are appended.
*
* Let n be the length of this character sequence just prior to
* execution of the {@code append} method. Then the character at
* index k in the new character sequence is equal to the character
* at index k in the old character sequence, if k is less
* than n; otherwise, it is equal to the character at index
* k-n in the argument {@code str}.
*
* @param str a string.
* @return a reference to this object.
*/
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;
}
这里面涉及到了他们的扩容机制,见下:
③ 构造包含与指定的{@code CharSequence}相同的字符
CharSequence指的是(s = null || s = (String)s || s = AbstractStringBuffer)s || AbstractStringBuilder)s)
/**
* Constructs a string buffer that contains the same characters
* as the specified {@code CharSequence}. The initial capacity of
* the string buffer is {@code 16} plus the length of the
* {@code CharSequence} argument.
*
* If the length of the specified {@code CharSequence} is
* less than or equal to zero, then an empty buffer of capacity
* {@code 16} is returned.
*
* @param seq the sequence to copy.
* @since 1.5
*/
public StringBuffer(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
/**
* Constructs a string builder that contains the same characters
* as the specified {@code CharSequence}. The initial capacity of
* the string builder is {@code 16} plus the length of the
* {@code CharSequence} argument.
*
* @param seq the sequence to copy.
*/
public StringBuilder(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
最终走的append()
方法,同样也涉及扩容机制。
// Documentation in subclasses because of synchro difference
@Override
public AbstractStringBuilder append(CharSequence s) {
if (s == null)
return appendNull();
if (s instanceof String)
return this.append((String)s);
if (s instanceof AbstractStringBuilder)
return this.append((AbstractStringBuilder)s);
return this.append(s, 0, s.length());
}
扩容机制
对于StringBuffer和StringBuilder的扩容机制可以只看一行代码。
int newCapacity = (value.length << 1) + 2;//value.length * 2 + 2
/**
* Returns a capacity at least as large as the given minimum capacity.
* Returns the current capacity increased by the same amount + 2 if
* that suffices.
* Will not return a capacity greater than {@code MAX_ARRAY_SIZE}
* unless the given minimum capacity is greater than that.
*
* @param minCapacity the desired minimum capacity
* @throws OutOfMemoryError if minCapacity is less than zero or
* greater than Integer.MAX_VALUE
*/
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;
}