java源碼解析之String類(五)

    /*
     * 切片函數,非常重要,這裏一定要牢記beginIndex是開始位置,endIndex是結束位置,區別於以前學的offset是開始位置,而count或length是個數和長度
     * 比如說,new String("abcdefg",1,3)得到的是bcd
     * 而 "abcdefg".substring(1,3)得到的是bc,也就是下標爲1和2的倆個字符,並不包括c
     */
    public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }
    public String substring(int beginIndex, int endIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if (endIndex > value.length) {
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        int subLen = endIndex - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen);
    }

    /*
     * 返回的是一個字符序列CharSequence,而CharSequence是一個接口,所有這裏需要的是CharSequence的實現類
     * 而String實現的最後一個接口就是CharSequence,所以其實這裏返回的就是String對象
     * 但是這是一個多態對象,他能調用的方法只有CharSequence接口中的幾個,所以此方法沒用,除非程序就需要一個CharSequence對象
     * 
     */
    public CharSequence subSequence(int beginIndex, int endIndex) {
        return this.substring(beginIndex, endIndex);
    }

    /*
     * 將指定的字符串連接到該字符串的末尾。 如果參數字符串的長度爲0 ,則返回此String對象。
     * 這裏使用了new String(buf, true)
     *  否則,返回一個String對象,表示一個字符序列,該字符序列是由該String對象表示的字符序列與由參數字符串表示的字符序列的級聯。 
     *  如果需要大量的字符串拼接,請使用StringBuffer和StringBuilder
     */
    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);
    }

    /*
     * 判斷此字符串是否匹配指定的regaex正則表達式,正則表達式有些複雜,需要一章來敘述,這裏不做贅述
     */
    public boolean matches(String regex) {
        return Pattern.matches(regex, this);
    }

    /*
     * 判斷此字符串是否包含指定的字符序列CharSequence,CharSequence在上面已經講過了
     */
    public boolean contains(CharSequence s) {
        return indexOf(s.toString()) > -1;
    }
    /*
     * 替換字符串中的某個字符,注意參數都是字符char類型
     * 例如:"gollong".replace("o","")的結果爲"gllng"
     */
    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;
    }


    /*
     * 替換字符串中的字字符串,識別方式爲正則表達式
     * replaceFirst只替換第一個
     * replaceAll爲全部替換
     */
    public String replaceFirst(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
    }
    public String replaceAll(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceAll(replacement);
    }
    public String replace(CharSequence target, CharSequence replacement) {
        return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this)
                .replaceAll(Matcher.quoteReplacement(replacement.toString()));
    }

    /*
     * 切割字符串,形參regex是一個正則表達式。limit用於限制String[]的長度
     * 例如,字符串"boo:and:foo"使用以下參數產生以下結果: 
     * Regex Limit         Result 
     * :       2       { "boo", "and:foo" } 
     * :       5       { "boo", "and", "foo" } 
     * :       -2      { "boo", "and", "foo" } 
     * o       5       { "b", "", ":and:f", "", "" } 
     * o       -2      { "b", "", ":and:f", "", "" } 
     * o       0       { "b", "", ":and:f" } 

     */
    public String[] split(String regex, int limit) {
        char ch = 0;
        if (((regex.value.length == 1 && ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1)
                || (regex.length() == 2 && regex.charAt(0) == '\\' && (((ch = regex.charAt(1)) - '0') | ('9' - ch)) < 0
                        && ((ch - 'a') | ('z' - ch)) < 0 && ((ch - 'A') | ('Z' - ch)) < 0))
                && (ch < Character.MIN_HIGH_SURROGATE || ch > Character.MAX_LOW_SURROGATE)) {
            int off = 0;
            int next = 0;
            boolean limited = limit > 0;
            ArrayList<String> list = new ArrayList<>();
            while ((next = indexOf(ch, off)) != -1) {
                if (!limited || list.size() < limit - 1) {
                    list.add(substring(off, next));
                    off = next + 1;
                } else { // last one
                    // assert (list.size() == limit - 1);
                    list.add(substring(off, value.length));
                    off = value.length;
                    break;
                }
            }
            // If no match was found, return this
            if (off == 0)
                return new String[] { this };

            // Add remaining segment
            if (!limited || list.size() < limit)
                list.add(substring(off, value.length));

            // Construct result
            int resultSize = list.size();
            if (limit == 0) {
                while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
                    resultSize--;
                }
            }
            String[] result = new String[resultSize];
            return list.subList(0, resultSize).toArray(result);
        }
        return Pattern.compile(regex).split(this, limit);
    }
    
    public String[] split(String regex) {
        return split(regex, 0);
    }

    /*
     * 去掉字符串兩端的空格,很有用的小方法
     */
    public String trim() {
        int len = value.length;
        int st = 0;
        char[] val = value; /* avoid getfield opcode */

        while ((st < len) && (val[st] <= ' ')) {
            st++;
        }
        while ((st < len) && (val[len - 1] <= ' ')) {
            len--;
        }
        return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
    }

    /*
     * toString返回這個對象本身,
     * 重點:我們總以爲直接輸出一個字符串對象可以打印其char數組的內容是因爲String重寫了toString方法
     *     我們認爲System.out.println(str)就是System.out.println(str.toString())
     *     其實不是的,我們很清楚的看到了,toString方法就是返回一個String對象,並不是遍歷
     *     於是乎我們得到了一個結論:
     *         System.out.println(str.toString())就是System.out.println(str)他們都依賴於String的特殊的實現機制
     *         這個機制就是:String s = "gollopng"就是創造對象並實例化
     *                  System.out.println(str)就是直接遍歷輸出
     */
    public String toString() {
        return this;
    }

    /*
     * 將字符串轉換爲char數組,此時聯想一下charAt方法,不要記混了
     */
    public char[] toCharArray() {
        // Cannot use Arrays.copyOf because of class initialization order issues
        char result[] = new char[value.length];
        System.arraycopy(value, 0, result, 0, value.length);
        return result;
    }
    
    /*
     * 返回字符串對象的規範表示,它遵循以下規則:對於任意兩個字符串 s 和 t,當且僅當 s.equals(t) 爲 true 時,s.intern() == t.intern() 才爲 true。
     * 儘管在輸出中調用intern方法並沒有什麼效果,但是實際上後臺這個方法會做一系列的動作和操作。在調用”gollong”.intern()方法的時候會返回”gollong”,
     * 但是這個方法會首先檢查字符串常量池中是否有”gollong”這個字符串,如果存在則該引用指向它,否則就將這個字符添加到字符串池中,然會再指向。
     */
    public native String intern();
    
    
    /*
     * 返回一個新的字符串,由 CharSequence elements的副本組成,並附有指定的delimiter的 delimiter 
     */
    public static String join(CharSequence delimiter, CharSequence... elements) {
        Objects.requireNonNull(delimiter);
        Objects.requireNonNull(elements);
        // Number of elements not likely worth Arrays.stream overhead.
        StringJoiner joiner = new StringJoiner(delimiter);
        for (CharSequence cs : elements) {
            joiner.add(cs);
        }
        return joiner.toString();
    }

    /*
     * 返回一個新 String的副本組成 CharSequence elements與指定的副本一起加入 delimiter 。
     */
    public static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements) {
        Objects.requireNonNull(delimiter);
        Objects.requireNonNull(elements);
        StringJoiner joiner = new StringJoiner(delimiter);
        for (CharSequence cs : elements) {
            joiner.add(cs);
        }
        return joiner.toString();
    }

    /*
     * toLowerCase(Locale locale):將字符串中所有小寫字符轉換爲大寫,其中locale用於指定自己的規則
     * toUpperCase(Locale locale):將字符串中所有大寫字符轉換爲小寫,其中locale用於指定自己的規則
     */
    public String toLowerCase(Locale locale) {
        if (locale == null) {
            throw new NullPointerException();
        }

        int firstUpper;
        final int len = value.length;

        /* Now check if there are any characters that need to be changed. */
        scan: {
            for (firstUpper = 0; firstUpper < len;) {
                char c = value[firstUpper];
                if ((c >= Character.MIN_HIGH_SURROGATE) && (c <= Character.MAX_HIGH_SURROGATE)) {
                    int supplChar = codePointAt(firstUpper);
                    if (supplChar != Character.toLowerCase(supplChar)) {
                        break scan;
                    }
                    firstUpper += Character.charCount(supplChar);
                } else {
                    if (c != Character.toLowerCase(c)) {
                        break scan;
                    }
                    firstUpper++;
                }
            }
            return this;
        }

        char[] result = new char[len];
        int resultOffset = 0; 
        System.arraycopy(value, 0, result, 0, firstUpper);

        String lang = locale.getLanguage();
        boolean localeDependent = (lang == "tr" || lang == "az" || lang == "lt");
        char[] lowerCharArray;
        int lowerChar;
        int srcChar;
        int srcCount;
        for (int i = firstUpper; i < len; i += srcCount) {
            srcChar = (int) value[i];
            if ((char) srcChar >= Character.MIN_HIGH_SURROGATE && (char) srcChar <= Character.MAX_HIGH_SURROGATE) {
                srcChar = codePointAt(i);
                srcCount = Character.charCount(srcChar);
            } else {
                srcCount = 1;
            }
            if (localeDependent || srcChar == '\u03A3' || // GREEK CAPITAL LETTER SIGMA
                    srcChar == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE
                lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale);
            } else {
                lowerChar = Character.toLowerCase(srcChar);
            }
            if ((lowerChar == Character.ERROR) || (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
                if (lowerChar == Character.ERROR) {
                    lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
                } else if (srcCount == 2) {
                    resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount;
                    continue;
                } else {
                    lowerCharArray = Character.toChars(lowerChar);
                }

                /* Grow result if needed */
                int mapLen = lowerCharArray.length;
                if (mapLen > srcCount) {
                    char[] result2 = new char[result.length + mapLen - srcCount];
                    System.arraycopy(result, 0, result2, 0, i + resultOffset);
                    result = result2;
                }
                for (int x = 0; x < mapLen; ++x) {
                    result[i + resultOffset + x] = lowerCharArray[x];
                }
                resultOffset += (mapLen - srcCount);
            } else {
                result[i + resultOffset] = (char) lowerChar;
            }
        }
        return new String(result, 0, len + resultOffset);
    }
    public String toLowerCase() {
        return toLowerCase(Locale.getDefault());
    }
    public String toUpperCase(Locale locale) {
        if (locale == null) {
            throw new NullPointerException();
        }
        int firstLower;
        final int len = value.length;
        scan: {
            for (firstLower = 0; firstLower < len;) {
                int c = (int) value[firstLower];
                int srcCount;
                if ((c >= Character.MIN_HIGH_SURROGATE) && (c <= Character.MAX_HIGH_SURROGATE)) {
                    c = codePointAt(firstLower);
                    srcCount = Character.charCount(c);
                } else {
                    srcCount = 1;
                }
                int upperCaseChar = Character.toUpperCaseEx(c);
                if ((upperCaseChar == Character.ERROR) || (c != upperCaseChar)) {
                    break scan;
                }
                firstLower += srcCount;
            }
            return this;
        }
        int resultOffset = 0;
        char[] result = new char[len]; 
        System.arraycopy(value, 0, result, 0, firstLower);

        String lang = locale.getLanguage();
        boolean localeDependent = (lang == "tr" || lang == "az" || lang == "lt");
        char[] upperCharArray;
        int upperChar;
        int srcChar;
        int srcCount;
        for (int i = firstLower; i < len; i += srcCount) {
            srcChar = (int) value[i];
            if ((char) srcChar >= Character.MIN_HIGH_SURROGATE && (char) srcChar <= Character.MAX_HIGH_SURROGATE) {
                srcChar = codePointAt(i);
                srcCount = Character.charCount(srcChar);
            } else {
                srcCount = 1;
            }
            if (localeDependent) {
                upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale);
            } else {
                upperChar = Character.toUpperCaseEx(srcChar);
            }
            if ((upperChar == Character.ERROR) || (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
                if (upperChar == Character.ERROR) {
                    if (localeDependent) {
                        upperCharArray = ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);
                    } else {
                        upperCharArray = Character.toUpperCaseCharArray(srcChar);
                    }
                } else if (srcCount == 2) {
                    resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount;
                    continue;
                } else {
                    upperCharArray = Character.toChars(upperChar);
                }
                int mapLen = upperCharArray.length;
                if (mapLen > srcCount) {
                    char[] result2 = new char[result.length + mapLen - srcCount];
                    System.arraycopy(result, 0, result2, 0, i + resultOffset);
                    result = result2;
                }
                for (int x = 0; x < mapLen; ++x) {
                    result[i + resultOffset + x] = upperCharArray[x];
                }
                resultOffset += (mapLen - srcCount);
            } else {
                result[i + resultOffset] = (char) upperChar;
            }
        }
        return new String(result, 0, len + resultOffset);
    }

    public String toUpperCase() {
        return toUpperCase(Locale.getDefault());
    }

    /*
     * 使用指定的格式字符串和參數返回格式化的字符串。 Object... args是可變參數
     */
    public static String format(String format, Object... args) {
        return new Formatter().format(format, args).toString();
    }

    /*
     * 使用指定的區域設置,格式字符串和參數返回格式化的字符串。 
     */
    public static String format(Locale l, String format, Object... args) {
        return new Formatter(l).format(format, args).toString();
    }

    /*
     * 下面是String通過靜態方法將其他類型轉換爲字符串
     * 總結:將其他類型轉換爲字符串有三種方法
     *     1.String的構造器:可以轉換byte[]、char[]、int[]
     *     2.String的靜態方法valueOf:可以轉換Object對象、char[]、boolean、char、int、long、float、double
     *     3.其他類型的toString方法:只要是重寫了toString,就可以轉換
     */
    public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();
    }
    public static String valueOf(char data[]) {
        return new String(data);
    }
    public static String valueOf(char data[], int offset, int count) {
        return new String(data, offset, count);
    }

    public static String copyValueOf(char data[], int offset, int count) {
        return new String(data, offset, count);
    }

    public static String copyValueOf(char data[]) {
        return new String(data);
    }

    public static String valueOf(boolean b) {
        return b ? "true" : "false";
    }
    public static String valueOf(char c) {
        char data[] = { c };
        return new String(data, true);
    }
    public static String valueOf(int i) {
        return Integer.toString(i);
    }
    public static String valueOf(long l) {
        return Long.toString(l);
    }
    public static String valueOf(float f) {
        return Float.toString(f);
    }
    public static String valueOf(double d) {
        return Double.toString(d);
    }

    

 

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