本文通過StringBuffer 源碼,來了解append(),方法。
============================================================================
str.append(""); 是用來拼接字元竄,一般人我不告訴他。
一、直接上示例:
public class TestString {
public static void main(String[] args) {
StringBuffer buffer = new StringBuffer();
buffer.append("hello ");
buffer.append("world!");
System.out.println(buffer); //結果 hello world!
}
}
二、斷點跟蹤:(以下都是jdk1.8源碼)
1、進入StringBuffer類的 append(String str) 方法: str = hello, 傳進來。
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence
{
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
}
2、調用了父類的方法super.append():str=hello ,傳到父類的方法。
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len); //count :存放的字元的長度 現在是0, len = 5
str.getChars(0, len, value, count);
count += len;
return this;
}
2.1、 進入 ensureCapacityInternal(), 判斷字元總長度有沒有超過 字元數組的容量值。
private void ensureCapacityInternal(int minimumCapacity) { // 0+5
// overflow-conscious code
if (minimumCapacity - value.length > 0) { //value.length 預設初始值為16
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
注意區分下面兩者:
value.length : 是 char[] value 數組的 長度,預設初始值 16.
str.length() :字元串的長度,(也可以了解為字元的個數)。
/**
* Returns the length (character count).
*
* @return the length of the sequence of characters currently
* represented by this object
*/
@Override
public int length() {
return count; //看看,傳回的count
}
2.2、 當minimumcapacity > value.length, 字元數組開始擴容。
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2; //容量擴大為 原來的2倍+2
if (newCapacity - minCapacity < 0) { //如果還是比字元總長度小, 那麼 總長度就設定為容量。
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
3、進入String類的方法 getChars(srcBegin,srcEnd, char [] dest, int destBegin );
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > value.length) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
難點:
難點a、這裡可能會比較不太明白, 在進入抽象父類的方法後, 又調用了String類的getChar() 方法。
注意: str.getChar(); 這裡的str 是是傳入 “hello”字元竄。 是以,其實這裡已經建立了一個String類,String str ="hello";
并且, String類,在内部定義了一個 字元數組,private final char[] value ; 字元串會被分解存放在這個數組裡面。是以
“hello”, 被存儲為 char [] value = {"h","e","l","l","o"}。如果了解這裡的話, 進入< 3 > 方法的幾個參數就好了解了。
難點b、System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd-srcBegin);
最後這個方法的參數值 : value, 到底代表的是那個類的 char[] 數組呢?
因為 <3 >方法是在String類中調用的, 是以value 所指的是 String 類中維護的 那個 char [] value = {"h","e","l","l","o"};
參數解釋:
srcBegin: 複制源數組的開始位置(數組下标), 例如: 這裡srcBegin= 0 , 是以從 字元 h 開始複制。
srcEnd : 源數組的結束位置, 這裡 srcEnd = len, "hello"的長度。
char dst[] : StringBuffer 存儲的字元數組。(StringBuffer 類一 維護了一個 字元數組 char value []), 因為命名都一樣,可能會有點搞混。
srcEnd -srcBegin: 要被複制的元素的個數。其實完全可以用 srcEnd 來表示就可以了。
4、最後進入System類的 方法 arraycopy();數組複制。
三、結論:
由此可以看出, StringBuffer拼接字元竄的 實質是:char類型數組的擴容複制。
============================================================================本文到此結束,後續内容繼續補充。