字符窜拼接方法 append() 源码解析

本文通过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类型数组的扩容复制。

============================================================================本文到此结束,后续内容继续补充。


猜你喜欢

转载自blog.csdn.net/qq_41694349/article/details/79424456