在 Java源码赏析(三)初识 String 类   中,我们已经大概理解了String的接口,接下来我们描述一下String的常用工具方法。

/**

 * 为了精简的String结构,之前提到的方法省略,重点介绍剩余的方法(省略构造方法、indexOf、lastIndexOf、valueOf)
*/
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence { private final char value[]; private int hash; // Default to 0 private static final long serialVersionUID = -6849794470754667710L; /** 指明需要实例化的字段 */
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0]; /** 省略CaseInsensitiveComparator()的实现,主要是用于按ASCII码的排序规则进行排序 */
public static final Comparator<String> CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator(); /** 实现Comparable<String> */
public int compareTo(String anotherString) {
...
} /** 覆盖hashCode() */
public int hashCode() {
...
} /** 覆盖父类equal() */
public boolean equals(Object anObject) {
...
} /** 覆盖父类toString() */
public String toString() {
return this;
} /**
* 实现CharSequence接口
* 共有length(), charAt(int index), subSequence(int beginIndex, int endIndex) 等
* 在实现subSequence()方法时使用了String中substring()方法
*/ /** 获取字符串长度 */
public int length() {
return value.length;
} /** 获取index位置的字符 */
public char charAt(int index) {
...
} /** 获取子字符序列 */
public CharSequence subSequence(int beginIndex, int endIndex) {
return this.substring(beginIndex, endIndex);
} /** 获取子串 */
public String substring(int beginIndex, int endIndex) {
...
}
/** 将字符串存入常量池并返回在常量池的引用 */
public native String intern(); /**分隔线*/

  将字符串str连接至末尾,创建一个新字符串*/
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);
} /** 将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;
} /** 返回是否被regex匹配*/
public boolean matches(String regex) {
return Pattern.matches(regex, this);
} /** 查看字符串s是否被包含*/
public boolean contains(CharSequence s) {
return indexOf(s.toString()) > -1;
} /** 替换第一个根据regex匹配到的字符串为replacement*/
public String replaceFirst(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
} /** 将regex匹配到的内容全部替换为replacement*/
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
} /** 将字符串target替换为replacement*/
public String replace(CharSequence target, CharSequence replacement) {
return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
} /** 根据regex分割limit次字符串*/
public String[] split(String regex, int limit) {
/* fastpath if the regex is a
(1)one-char String and this character is not one of the
RegEx's meta characters ".$|()[{^?*+\\", or
(2)two-char String and the first char is the backslash and
the second is not the ascii digit or ascii letter.
*/
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);
} /** 根据regex分隔字符串*/
public String[] split(String regex) {
return split(regex, 0);
} /** 将elements字符串数组中插入delimiter字符串 比如 String.join(",", {"a", "b", "c"}) == "a,b,c" */
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();
} /** 同上,数组改为了集合*/
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();
} /** 全部转化为小写字母*/
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; /* result may grow, so i+resultOffset
* is the write location in result */ /* Just copy the first few lowerCase characters. */
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; /* Now check if there are any characters that need to be changed. */
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;
} /* result may grow, so i+resultOffset is the write location in result */
int resultOffset = 0;
char[] result = new char[len]; /* may grow */ /* Just copy the first few upperCase characters. */
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);
} /* Grow result if needed */
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());
} /** 去除字符串前后的空格*/
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;
} /** 转化为字符数组*/
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;
} /** 格式化字符串,便于输出*/
public static String format(String format, Object... args) {
return new Formatter().format(format, args).toString();
} /** 使用指定的地区l,格式化字符串,便于输出*/
public static String format(Locale l, String format, Object... args) {
return new Formatter(l).format(format, args).toString();
} /** 根据data字符数组从offset开始复制count个字符*/
public static String valueOf(char data[], int offset, int count) {
return new String(data, offset, count);
} /** 根据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";
} ...
}

未完,待续

Java源码赏析(五)再识 String 类的更多相关文章

  1. Java源码赏析(一)Object 类

    写这个系列的原因,其实网上已经有无数源码分析的文章了,多一篇不多,少一篇不少,但为什么还要写这部分文章呢?于私,其一,上班族已经很久没有打过完整的一整段有意义的话,算是锻炼个人的书写.总结能力,其二, ...

  2. Java源码赏析(三)初识 String 类

    由于String类比较复杂,现在采用多篇幅来讲述 这一期主要从String使用的关键字,实现的接口,属性以及覆盖的方法入手.省略了大部分的字符串操作,比如split().trim().replace( ...

  3. Java源码赏析(六)Class<T> 类

    目的 Class 类是每一个程序员都必须了解的,也是使用反射机制的基础. 这篇文章将Class 类的公共方法大致介绍了一遍(省略了安全.枚举.断言.注解相关代码). 代码 package java.l ...

  4. java源码学习(一)String

    String表示字符串,Java中所有字符串的字面值都是String类的实例,例如"ABC".字符串是常量,在定义之后不能被改变,字符串缓冲区支持可变的字符串.因为 String ...

  5. Java源码赏析(四)Java常见注解

    元注解 @Target :标识注解的目标,默认为所有 ElementType.TYPE(用于类) ElementType.FIELD(用于域,包括enum) ElementType.METHOD(用于 ...

  6. Java 源码赏析 - java.lang - Void

    被人鄙视了,于是也来读读源码... package java.lang; /** * The Void class is an uninstantiable placeholder class to ...

  7. Java入门篇(五)——字符串/String类

    前面在举例时有出现过String的例子,当时肯定有一部分朋友不知道这个是做什么用的.其实String类是Java中一个比较特殊的类,字符串即String类,它不是Java的基本数据类型之一,但可以像基 ...

  8. Java源码赏析(六)Java String 三顾

    在大致了解了String之后,可能有的读者发现了,我们并没有谈到CharSequence接口. 原因是在这一节,CharSequence要和StringBuilder(Java1.5).StringB ...

  9. Java源码赏析(二)Java常见接口

    一.Comparable接口 package java.lang; import java.util.*; public interface Comparable<T> { /** * i ...

随机推荐

  1. Improved robustness of reinforcement learning policies upon conversion to spiking neuronal network platforms applied to Atari Breakout game

    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! arXiv:1903.11012v3 [cs.LG] 19 Aug 2019 Neural Networks, 25 November 2 ...

  2. 如何下载gitbub中的单个文件

    1.进入Github文件夹,打开对应文件: 2.右键单击Raw,然后目标另存为即可.

  3. pandas外部数据的读取构造数据框-文本文件读取(一种utf-8中文编码乱码处理经验)

    上面一篇文章有记录pandas构造数据框的方式有二维数组,字典,嵌套的列表和元组等,本篇用于介绍通过外部数据读取的方式来构造数据框. python读取外部数据集的时候,这些数据集可能包含在文本文件(c ...

  4. 玩转Spring——Spring IOC/DI

    什么是IOCioc :Inversion of Control,即控制反转. 它不是一种技术,而是一种设计思想,即java程序中获取对象的方式发生反转,由最初的new方式创建,转变成由第三方框架创建. ...

  5. Swift Expressible literal

    Swift Expressible Literal 引子 从一个面试题说起.有如下代码: struct Book { let name: String } let book: Book = " ...

  6. Redis秒杀系统架构设计-微信抢红包

    导读 前二天我写了一篇,Redis高级项目实战(点我直达),SpringBoot整合Redis附源码(点我直达),今天我们来做一下Redis秒杀系统的设计.当然啦,Redis基础知识还不过关的,先去加 ...

  7. [PyTorch 学习笔记] 3.2 卷积层

    本章代码:https://github.com/zhangxiann/PyTorch_Practice/blob/master/lesson3/nn_layers_convolution.py 这篇文 ...

  8. IDEA导入Eclipse的快捷键KeyMap

    说在前面的话 现在由于IDEA编辑器越来越火,因此很多程序员都从eclipse转入IDEA,转入后确实发现很强大的编辑器,但是一直为快捷键而忧愁,因为eclipse毕竟跟随了自己好多年了,突然更换编辑 ...

  9. SpringBoot事务使用和回滚

    Springboot中事务的使用: 1.启动类加上@EnableTransactionManagement注解,开启事务支持(其实默认是开启的). 2.在使用事务的public(只有public支持事 ...

  10. HDOJ 1003

    动态规划一直AC不了竟然是因为一厢情愿的多加了一个#! printf("Case #%d:\n",count); --------------------------------- ...