String、StringBuffer和StringBuilder源碼解析


1.String

1.1類的定義

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence

String類在定義時候使用final關鍵字進行修飾,限制了這個類無法被繼承,里面的方法也無法被重寫。

同時它還實現了Serializable接口、Comparable接口,以及CharSequence接口三個接口:

  • Serializable:序列化接口,如果允許對象被序列化需要實現該類。
  • Comparable:比較對象大小的接口,用來定義對象之間如何進行大小的比較。
  • CharSequence:字符序列接口,相比String類,它是一個更為廣泛的可讀可寫字符序列,而String類是只可讀的。

1.2類的成員變

    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0

String類中常用的兩個成員變量value、hash。

  • value:字符類型的數組,用來存放我們所保存的字符串,每一個字符串都會被拆開作為字符來進行存儲
  • hash:對應字符串的hash值。

1.3常用方法

length():返回value數組的長度。

    public int length() {
        return value.length;
    }

 

indexOf(str):獲取在字符串中某個字符串的起始位置。這里其實也是用的遍歷,從指定的開始位置起,一直遍歷直到找到目標字符串,或者直到源字符串的最后一位(其實是最后一位減去目標字符串的長度)。

    public int indexOf(String str) {
        return indexOf(str, 0);
    }

    public int indexOf(String str, int fromIndex) {
        return indexOf(value, 0, value.length,
                str.value, 0, str.value.length, fromIndex);
    }

    static int indexOf(char[] source, int sourceOffset, int sourceCount,
            char[] target, int targetOffset, int targetCount,
            int fromIndex) {
        if (fromIndex >= sourceCount) {
            return (targetCount == 0 ? sourceCount : -1);
        }
        if (fromIndex < 0) {
            fromIndex = 0;
        }
        if (targetCount == 0) {
            return fromIndex;
        }

        char first = target[targetOffset];
        int max = sourceOffset + (sourceCount - targetCount);

        for (int i = sourceOffset + fromIndex; i <= max; i++) {
            /* Look for first character. */
            if (source[i] != first) {
                while (++i <= max && source[i] != first);
            }

            /* Found first character, now look at the rest of v2 */
            if (i <= max) {
                int j = i + 1;
                int end = j + targetCount - 1;
                for (int k = targetOffset + 1; j < end && source[j]
                        == target[k]; j++, k++);

                if (j == end) {
                    /* Found whole string. */
                    return i - sourceOffset;
                }
            }
        }
        return -1;
    }

 

compareTo(str):比較兩個字符串的大小,采用的是逐個字符來進行比較(比較ASCII碼)。

    public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

 

1.4總結

String類是一個可序列化,可按照字符大小進行排序,不可繼承、只讀的字符序列類。

 

2.StringBuilder

2.1類定義

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence

StringBuilder和String的定義類似,同樣被final關鍵字修飾,限定了無法被繼承,同時繼承Serializable和CharSequence兩個接口。

同時最它多繼承了一個抽象類AblstractStringBuilder。

2.2成員變量

在StringBuilder中沒有再定義其他的成員變量,所使用的底層存放數據的變量來自於父類AbstractStringBuilder。

在AbstractStringBuilder中,定義了三個成員變量

    char[] value;

    int count;

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
  • value:字符數組,用來存放傳入的字符串。
  • count:int類型,記錄value中存放元素的長度。
  • MAX_ARRAY_SIZE:靜態常量,代指允許value數組的最大長度。

2.3常用方法

append(str):相比String只讀的屬性,StringBuilder允許我們對其進行寫操作。但是由於底層存放數據的是一個數組,因此每次都需要進行一個擴容的判斷。如果count+入參字符串的長度大於當前數組value的長度,就需要進行擴容,每次擴容后的數組長度=原長度*2+2。

    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;
    }

    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

    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;
    }

2.4總結

StringBuilder補充了String只能讀不能寫的屬性,采用對數組擴容的操作,允許程序員對String類型來進行寫操作。

 

3.StringBuffer

3.1類定義

 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence

StringBuffer的定義與StringBuilder類似,同樣繼承了AbstractStringBuilder抽象類,實現了Serializable和CharSequence接口。

3.2成員變量

StringBuffer的成員變量和StringBuilder一樣,同樣適用在AbstractStringBuilder中定義好的字符類型數組value和int類型count。

3.3常用方法

append(str):與StringBuilder類似的,兩個類都是通過調用AbstractStringBuilder中的append(str)方法來添加字符串。

區別在於StringBuffer的方法定義上多了一個關鍵字:Synchronized。通過這個關鍵字,來保證我們對字符串的寫操作的線程安全。

    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

toString():和StringBuilder的toString()方法不一樣,這里在StringBuffer中就已經完成了對字符數組的復制,如果連續調用toString()方法,實際返回的都是同一個String對象。而在StringBuilder中,由於數組的復制是發生在String類里面,因此每次調用后返回的都是不同的String對象。

    @Override
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

 

3.4總結

StringBuffer在Stringbuilder實現了字符串寫操作的基礎上,又添加了對它的線程安全方面的維護,通過查看源碼,可見都是通過在方法上添加synchronized關鍵字來顯示的。這樣雖然可以保證線程安全,但是也在一定程度上,舍棄了部分性能。不過在jdk1.5之后對鎖的優化,新增了偏向鎖、輕量級鎖后,如果我們對字符串的寫操作不涉及多線程的時候,StringBuffer和StringBuilder的資源損耗是幾乎類似的。但如果一旦涉及多線程,StringBuffer則能更好的保障我們的線程安全。

 

4.總結

String類是java中定義用來保存一個字符序列的對象,但是對它的操作只有讀,而沒有寫。所有的寫操作實際都是返回了一個新的字符串對象。

StringBuilder類在String類的基礎上,增加了對字符序列的寫操作,采用底層數組擴容的方式,來允許添加新的字符串,或刪除里面原有的字符串。

StringBuffer類由在StringBuilder類的基礎上,既滿足了對字符序列的寫操作,又保證了操作的線程安全。因此在實際情況下,優先推薦使用StringBuffer類。

 

 

成員變量

String類型


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM