源碼面前,原形畢露之String源碼閱讀

記錄下閱讀源碼過程中遇到的有用的知識

1.String位final類,不可繼承,其聲明爲
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence,String的內容由
private char value[]`存儲.

2.方法public int codePointAt(int index) 直接返回索引下的char元素的Unicode code point,如

String Str = "012345Str";
        //直接返回索引下的char元素的Unicode code point
        System.out.println(Str.codePointAt(0));

可以得到0的Unicode code point爲48,這樣獲得字母數字和特殊符號的ASCII碼很方便。
源碼實現爲:

public int codePointAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return Character.codePointAtImpl(value, index, value.length);
    }

3.函數public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)可以將String截取某部分放到char []中,函數的實現方法爲

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

還不如先使用substring()截取某一段,再使用toCharArray()轉換成char[]更加方便。

4.重寫equals方法

public boolean equals(Object anObject) {
        if (this == anObject) {//當前要比較對象爲同一對象,返回true,滿足自反性
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {//比較每個元素是否相等
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

5.String類對compareTo方法的實現方法

public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);//以最小長度的string爲基準
        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;//返回值爲第一個不等char元素的差值
            }
            k++;
        }
        return len1 - len2;//返回值爲兩個String的長度差
    }

當然,這種版本的compareTo方法不會令所有人滿意,比如我就不太滿意,哈哈。

6.startsWith(String prefix,int rooffset)方法.該方法用於判斷String是否以prefix爲前綴,這個方法實現起來比較簡單。

public boolean startsWith(String prefix, int toffset) {
        char ta[] = value;
        int to = toffset;
        char pa[] = prefix.value;
        int po = 0;
        int pc = prefix.value.length;
        // Note: toffset might be near -1>>>1.
        if ((toffset < 0) || (toffset > value.length - pc)) {
            return false;
        }
        while (--pc >= 0) {
            if (ta[to++] != pa[po++]) {
                return false;
            }
        }
        return true;
    }

public boolean endsWith(String suffix) 判斷String是否以suffix爲後綴,直接調用startsWith就可以了。

public boolean endsWith(String suffix) {
        return startsWith(suffix, value.length - suffix.value.length);
    }

7.重寫hashCode()方法.

 public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

使用了一個簡單的多項式散列函數算出了hash值,簡單的hash函數可以降低計算開銷,加快程序速度(在滿足hash要求的前提下),由 h = 31 * h + val[i]可以看出,不同的String完全有可能具有相同的hashCode,所以只根據hashCode值相同不能說明兩個String相等,需要通過equals()方法才能準確地判斷。

8.字符串連接函數contact()

public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }

做字符串連接時比較方便

        String Str = "012345Str";
        System.out.println(Str.concat(" I love Java"));

9.字符替換函數repalce(char oldChar,char newChar),用於將String中所有的oldChar替換爲newChar.

 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;
                }
            }
            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++;
                }
                return new String(buf, true);
            }
        }
        return this;
    }

10.正則表達式匹配函數public boolean matches(String regex).

public boolean matches(String regex) {
        return Pattern.matches(regex, this);
    }

如:

String str = "[email protected]";
        // 郵箱驗證規則
        String regEx = "[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\\.){1,3}[a-zA-z\\-]{1,}";
        // 編譯正則表達式
        System.out.println(str.matches(regEx));

打印結果爲true.

11.正則表達式替換函數replaceAll(String regex, String replacement)

public String replaceAll(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceAll(replacement);
    }

12.String的最後一個方法就是public native String intern();方法了,方法的作用javadoc裏說得很清楚:

/**
     * Returns a canonical representation for the string object.
     * <p>
     * A pool of strings, initially empty, is maintained privately by the
     * class {@code String}.
     * <p>
     * When the intern method is invoked, if the pool already contains a
     * string equal to this {@code String} object as determined by
     * the {@link #equals(Object)} method, then the string from the pool is
     * returned. Otherwise, this {@code String} object is added to the
     * pool and a reference to this {@code String} object is returned.
     * <p>
     * It follows that for any two strings {@code s} and {@code t},
     * {@code s.intern() == t.intern()} is {@code true}
     * if and only if {@code s.equals(t)} is {@code true}.
     * <p>
     * All literal strings and string-valued constant expressions are
     * interned. String literals are defined in section 3.10.5 of the
     * <cite>The Java&trade; Language Specification</cite>.
     *
     * @return  a string that has the same contents as this string, but is
     *          guaranteed to be from a pool of unique strings.
     */

還沒找到intern()的源碼,哈哈

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章