介绍
AbstractStringBuilder这个抽象类是StringBuilder和StringBuffer的直接父类,而且定义了很多方法,因此在学习这两个类之前建议先学习 AbstractStringBuilder抽象类
该类在源码中注释是以JDK1.5开始作为前两个类的父类存在的
abstract class AbstractStringBuilder implements Appendable, CharSequence
实现了两个接口,其中CharSequence这个字符序列的接口已经很熟悉了:
该接口规定了需要实现该字符序列的长度:length();
可以取得下标为index的的字符:charAt(int index);
可以得到该字符序列的一个子字符序列: subSequence(int start, int end);
规定了该字符序列的String版本(重写了父类Object的toString()):toString();
Appendable接口顾名思义,定义添加的’规则’:
append(CharSequence csq) throws IOException:如何添加一个字符序列
append(CharSequence csq, int start, int end) throws IOException:如何添加一个字符序列的一部分
append(char c) throws IOException:如何添加一个字符
常量&变量
/**
* The value is used for character storage.
* 该字符序列的具体存储 没有被final修饰,表示可以不断扩容
*/
char[] value;
/**
* The count is the number of characters used.
* 实际存储的数量
*/
int count;
/**
* The maximum size of array to allocate (unless necessary).
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
* 最大数组长度
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
构造方法
/**
* This no-arg constructor is necessary for serialization of subclasses.
*/
AbstractStringBuilder() {
}
/**
* Creates an AbstractStringBuilder of the specified capacity.
*/
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
常用方法
length()
/**
* Returns the length (character count).
*
* @return the length of the sequence of characters currently
* represented by this object
* 返回已经存储的实际长度(就是count值)
*/
@Override
public int length() {
return count;
}
capacity()
/**
* Returns the current capacity. The capacity is the amount of storage
* available for newly inserted characters, beyond which an allocation
* will occur.
*
* @return the current capacity
* 得到目前该value数组的实际大小
*/
public int capacity() {
return value.length;
}
ensureCapacity
/**
* Ensures that the capacity is at least equal to the specified minimum.
* If the current capacity is less than the argument, then a new internal
* array is allocated with greater capacity. The new capacity is the
* larger of:
* <ul>
* <li>The {@code minimumCapacity} argument.
* <li>Twice the old capacity, plus {@code 2}.
* </ul>
* If the {@code minimumCapacity} argument is nonpositive, this
* method takes no action and simply returns.
* Note that subsequent operations on this object can reduce the
* actual capacity below that requested here.
*
* @param minimumCapacity the minimum desired capacity.
* 确保容量至少等于指定的最小值。如果当前容量小于参数,则分配一个具有更大容量的新数组
*
*/
public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > 0)
ensureCapacityInternal(minimumCapacity);
}
/**
* For positive values of {@code minimumCapacity}, this method
* behaves like {@code ensureCapacity}, however it is never
* synchronized.
* If {@code minimumCapacity} is non positive due to numeric
* overflow, this method throws {@code OutOfMemoryError}.
*/
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
//扩容的实现
if (minimumCapacity - value.length > 0) {
//拷贝一个minimumCapacity大小的新数组
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
/**
* 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;
}
private int hugeCapacity(int minCapacity) {
//超出最大值,报错
if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
throw new OutOfMemoryError();
}
//再次确定新数组的容量大小
return (minCapacity > MAX_ARRAY_SIZE)
? minCapacity : MAX_ARRAY_SIZE;
}
trimToSize
/**
* Attempts to reduce storage used for the character sequence.
* If the buffer is larger than necessary to hold its current sequence of
* characters, then it may be resized to become more space efficient.
* Calling this method may, but is not required to, affect the value
* returned by a subsequent call to the {@link #capacity()} method.
* 如果value数组的容量有多余的,那么就把多余的全部都释放掉
*/
public void trimToSize() {
//数组的长度大于当前存储的个数
if (count < value.length) {
//拷贝count大小的新数组
value = Arrays.copyOf(value, count);
}
}
setLength
/**
* Sets the length of the character sequence.
* The sequence is changed to a new character sequence
* whose length is specified by the argument. For every nonnegative
* index <i>k</i> less than {@code newLength}, the character at
* index <i>k</i> in the new character sequence is the same as the
* character at index <i>k</i> in the old sequence if <i>k</i> is less
* than the length of the old character sequence; otherwise, it is the
* null character {@code '\u005Cu0000'}.
*
* In other words, if the {@code newLength} argument is less than
* the current length, the length is changed to the specified length.
* <p>
* If the {@code newLength} argument is greater than or equal
* to the current length, sufficient null characters
* ({@code '\u005Cu0000'}) are appended so that
* length becomes the {@code newLength} argument.
* <p>
* The {@code newLength} argument must be greater than or equal
* to {@code 0}.
*
* @param newLength the new length
* @throws IndexOutOfBoundsException if the
* {@code newLength} argument is negative.
* 强制增大实际长度count的大小,容量如果不够就用 expandCapacity()扩大;
* 将扩大的部分全部用’\0’(ASCII码中的null)来初始化
*/
public void setLength(int newLength) {
if (newLength < 0)
throw new StringIndexOutOfBoundsException(newLength);
//判断是否需要扩容
ensureCapacityInternal(newLength);
if (count < newLength) {
//填充数组
Arrays.fill(value, count, newLength, '\0');
}
count = newLength;
}
charAt
/**
* Returns the {@code char} value in this sequence at the specified index.
* The first {@code char} value is at index {@code 0}, the next at index
* {@code 1}, and so on, as in array indexing.
* <p>
* The index argument must be greater than or equal to
* {@code 0}, and less than the length of this sequence.
*
* <p>If the {@code char} value specified by the index is a
* <a href="Character.html#unicode">surrogate</a>, the surrogate
* value is returned.
*
* @param index the index of the desired {@code char} value.
* @return the {@code char} value at the specified index.
* @throws IndexOutOfBoundsException if {@code index} is
* negative or greater than or equal to {@code length()}.
* 得到下标为index的字符
*/
@Override
public char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index];
}
codePointAt
/**
* Returns the character (Unicode code point) at the specified
* index. The index refers to {@code char} values
* (Unicode code units) and ranges from {@code 0} to
* {@link #length()}{@code - 1}.
*
* <p> If the {@code char} value specified at the given index
* is in the high-surrogate range, the following index is less
* than the length of this sequence, and the
* {@code char} value at the following index is in the
* low-surrogate range, then the supplementary code point
* corresponding to this surrogate pair is returned. Otherwise,
* the {@code char} value at the given index is returned.
*
* @param index the index to the {@code char} values
* @return the code point value of the character at the
* {@code index}
* @exception IndexOutOfBoundsException if the {@code index}
* argument is negative or not less than the length of this
* sequence.
* 返回指定索引处的字符(Unicode码点)
*/
public int codePointAt(int index) {
if ((index < 0) || (index >= count)) {
throw new StringIndexOutOfBoundsException(index);
}
return Character.codePointAtImpl(value, index, count);
}
getChars
/**
* Characters are copied from this sequence into the
* destination character array {@code dst}. The first character to
* be copied is at index {@code srcBegin}; the last character to
* be copied is at index {@code srcEnd-1}. The total number of
* characters to be copied is {@code srcEnd-srcBegin}. The
* characters are copied into the subarray of {@code dst} starting
* at index {@code dstBegin} and ending at index:
* <pre>{@code
* dstbegin + (srcEnd-srcBegin) - 1
* }</pre>
*
* @param srcBegin start copying at this offset.
* @param srcEnd stop copying at this offset.
* @param dst the array to copy the data into.
* @param dstBegin offset into {@code dst}.
* @throws IndexOutOfBoundsException if any of the following is true:
* <ul>
* <li>{@code srcBegin} is negative
* <li>{@code dstBegin} is negative
* <li>the {@code srcBegin} argument is greater than
* the {@code srcEnd} argument.
* <li>{@code srcEnd} is greater than
* {@code this.length()}.
* <li>{@code dstBegin+srcEnd-srcBegin} is greater than
* {@code dst.length}
* </ul>
* 将value[]的[srcBegin, srcEnd)拷贝到dst[]数组的desBegin开始处
*/
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
{
if (srcBegin < 0)
throw new StringIndexOutOfBoundsException(srcBegin);
if ((srcEnd < 0) || (srcEnd > count))
throw new StringIndexOutOfBoundsException(srcEnd);
if (srcBegin > srcEnd)
throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
substring
/**
* Returns a new {@code String} that contains a subsequence of
* characters currently contained in this character sequence. The
* substring begins at the specified index and extends to the end of
* this sequence.
*
* @param start The beginning index, inclusive.
* @return The new string.
* @throws StringIndexOutOfBoundsException if {@code start} is
* less than zero, or greater than the length of this object.
* 得到子字符串
*/
public String substring(int start) {
return substring(start, count);
}
/**
* Returns a new {@code String} that contains a subsequence of
* characters currently contained in this sequence. The
* substring begins at the specified {@code start} and
* extends to the character at index {@code end - 1}.
*
* @param start The beginning index, inclusive.
* @param end The ending index, exclusive.
* @return The new string.
* @throws StringIndexOutOfBoundsException if {@code start}
* or {@code end} are negative or greater than
* {@code length()}, or {@code start} is
* greater than {@code end}.
*/
public String substring(int start, int end) {
if (start < 0)
throw new StringIndexOutOfBoundsException(start);
if (end > count)
throw new StringIndexOutOfBoundsException(end);
if (start > end)
throw new StringIndexOutOfBoundsException(end - start);
return new String(value, start, end - start);
}
subSequence
/**
* Returns a new character sequence that is a subsequence of this sequence.
*
* <p> An invocation of this method of the form
*
* <pre>{@code
* sb.subSequence(begin, end)}</pre>
*
* behaves in exactly the same way as the invocation
*
* <pre>{@code
* sb.substring(begin, end)}</pre>
*
* This method is provided so that this class can
* implement the {@link CharSequence} interface.
*
* @param start the start index, inclusive.
* @param end the end index, exclusive.
* @return the specified subsequence.
*
* @throws IndexOutOfBoundsException
* if {@code start} or {@code end} are negative,
* if {@code end} is greater than {@code length()},
* or if {@code start} is greater than {@code end}
* @spec JSR-51
* 得到一个子字符序列
*/
@Override
public CharSequence subSequence(int start, int end) {
return substring(start, end);
}
reverse
/**
* Causes this character sequence to be replaced by the reverse of
* the sequence. If there are any surrogate pairs included in the
* sequence, these are treated as single characters for the
* reverse operation. Thus, the order of the high-low surrogates
* is never reversed.
*
* Let <i>n</i> be the character length of this character sequence
* (not the length in {@code char} values) just prior to
* execution of the {@code reverse} method. Then the
* character at index <i>k</i> in the new character sequence is
* equal to the character at index <i>n-k-1</i> in the old
* character sequence.
*
* <p>Note that the reverse operation may result in producing
* surrogate pairs that were unpaired low-surrogates and
* high-surrogates before the operation. For example, reversing
* "\u005CuDC00\u005CuD800" produces "\u005CuD800\u005CuDC00" which is
* a valid surrogate pair.
*
* @return a reference to this object.
* 将value给倒序存放
* (注意改变的就是本value,而不是创建了一个新的AbstractStringBuilder然后value为倒序)
*/
public AbstractStringBuilder reverse() {
boolean hasSurrogates = false;
int n = count - 1;
for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j;
char cj = value[j];
char ck = value[k];
value[j] = ck;
value[k] = cj;
if (Character.isSurrogate(cj) ||
Character.isSurrogate(ck)) {
hasSurrogates = true;
}
}
if (hasSurrogates) {
reverseAllValidSurrogatePairs();
}
return this;
}
github:AbstractStringBuilder源码
如文章有问题请留言,谢谢~