java源码解析之String类
Posted GolLong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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); }
以上是关于java源码解析之String类的主要内容,如果未能解决你的问题,请参考以下文章