/* * 切片函數,非常重要,這裏一定要牢記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); }