首頁 > Java > java教程 > String原始碼的實例解讀

String原始碼的實例解讀

零下一度
發布: 2017-06-29 09:55:32
原創
1519 人瀏覽過

String類別內部維護了一個char[]類型的value用來儲存字串,相對來說原始碼較為簡單些。

1.不可變性

String的不可變主要體現在三個方面:

  • String類別被定義為final類型,不可被繼承

  • String中的value[]被定義為final

  • String中的所有產生新的String的操作底層都會呼叫Array.copy或System.copy來產生一個新的String物件

#2.建構子,String的建構子較為簡單,但以下幾個較為特殊
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
    
    String(char[] value, boolean share) {
        // assert share : "unshared not supported";
        this.value = value;
    }
登入後複製

以上兩個是較為特殊的一類建構函數,第一個用一個現成的String來初始化一個新的String對象,建構方法直接將新的String對象的value指向舊的value對象。由於String是不可變的,所以這裡不需要重新copy一份value的物件。第二個建構方法看似會破壞String類型的不可變性(當參數value變化時String也會改變),但建構方法並沒有宣告為public,只允許在套件內使用,被宣告為public的String( char value[])底層呼叫的是Array.copy來實現底層資料拷貝的,上述的兩個建構函式已經不建議使用

    public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }
登入後複製

上面這個建構子較為典型,許多其他的建構子都與其類似或底層呼叫了該建構函數,入參是一個char數組(byte[]),offset偏移位置及count偏移量。底層呼叫Arrays.copy函數來進行深度複製。

    public String(StringBuffer buffer) {
        synchronized(buffer) {  //保证线程安全
            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
        }
    }
    
    public String(StringBuilder builder) {
        this.value = Arrays.copyOf(builder.getValue(), builder.length());
    }
登入後複製

上述兩個建構子入參分別是StringBuffer和StringBuilder,底層都是呼叫Arrays.copyOf,唯一不同的是StringBuffer是線程安全的,所有呼叫時都需要用synchronized關鍵字。

3.其他方法
    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;
    }
    
    static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
            char[] target, int targetOffset, int targetCount,
            int fromIndex) {
        /*
         * Check arguments; return immediately where possible. For
         * consistency, don&#39;t check for null str.
         */
        int rightIndex = sourceCount - targetCount;
        if (fromIndex < 0) {
            return -1;
        }
        if (fromIndex > rightIndex) {
            fromIndex = rightIndex;
        }
        /* Empty string always matches. */
        if (targetCount == 0) {
            return fromIndex;
        }

        int strLastIndex = targetOffset + targetCount - 1;
        char strLastChar = target[strLastIndex];
        int min = sourceOffset + targetCount - 1;
        int i = min + fromIndex;

        startSearchForLastChar:
        while (true) {
            while (i >= min && source[i] != strLastChar) {
                i--;
            }
            if (i < min) {
                return -1;
            }
            int j = i - 1;
            int start = j - (targetCount - 1);
            int k = strLastIndex - 1;

            while (j > start) {
                if (source[j--] != target[k--]) {
                    i--;
                    continue startSearchForLastChar;
                }
            }
            return start - sourceOffset + 1;
        }
    }
登入後複製

indexOf和lastIndexOf主要是index和lastIndex函數的底層調用,通讀程式碼會發現底層實作並沒有特別牛逼的kmp演算法,仍然是一個字元一個字元掃描實現的。其中lastIndexOf還是用了continue startSearchForLastChar;相對來說比較少見。

    public String replace(char oldChar, char newChar) {
        if (oldChar != newChar) {
            int len = value.length;
            int i = -1;
            char[] val = value; /* avoid getfield opcode */

            while (++i < len) {
                if (val[i] == oldChar) {
                    break;
                }
            }
            //如果找不到则返回this
            if (i < len) {
                char buf[] = new char[len];
                for (int j = 0; j < i; j++) {
                    buf[j] = val[j];
                }
                while (i < len) {
                    char c = val[i]; //替换
                    buf[i] = (c == oldChar) ? newChar : c;
                    i++;
                }
                //返回新的String,利用上述包内的非public构造函数
                return new String(buf, true);
            }
        }
        return this;
    }
登入後複製

replace用於將String物件中的一個字元替換為另一個字符,如果找不到製定的字元則返回本身,如果找到則會另建一個新的String物件傳回。

---恢復內容結束---

#

以上是String原始碼的實例解讀的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板