接着上回String的源码分析:点击打开链接,此次接着分析String的源码进行分析
0 基础准备
静态内部类:当不需要内部类对象和外部类对象之间有联系,那么可以将内部类声明为static,静态内部类的实现不依赖域外部类的实例化,不论外部类的对象是否存在,都不影响内部类对象的实例化。
1-12 定义私有静态内部类— 忽略字符大小写的比较器
public static final Comparator<String> CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator();
/**
* 大小写不敏感的比较器
*/
private static class CaseInsensitiveComparator
implements Comparator<String>, java.io.Serializable {
// use serialVersionUID from JDK 1.2.2 for interoperability
private static final long serialVersionUID = 8575799808933029326L;
public int compare(String s1, String s2) {
int n1 = s1.length();
int n2 = s2.length();
int min = Math.min(n1, n2);
for (int i = 0; i < min; i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
if (c1 != c2) {
c1 = Character.toUpperCase(c1);
c2 = Character.toUpperCase(c2);
if (c1 != c2) {
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2);
if (c1 != c2) {
// No overflow because of numeric promotion
return c1 - c2;
}
}
}
}
return n1 - n2;
}
/** Replaces the de-serialized object. */
private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
}
return CASE_INSENSITIVE_ORDER.compare(this, str);
首先判断参数beginIndex的参数是否合法,然后使用的是String的一个构造函数String(char[] value,int offset,int count),这个从offset的位置开始,count个字符,进行构造成一个字符串。这个构造函数底层使用的是Arrays.copyOfRange方法,将原数据,拷贝到String对象的内部数组。
1-15 substring(int beginIndex.int endIndex)与1-14的方法不同就在于count值不同,有endIndex的方法,调用String的构造函数时,传递的是终止位序endIndex-startIndex的值
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);
}
/**
* 截取子串的方法使用的构造函数是String(char[] value,int offset,int count)
* beginIndex是offset,count是endIndex-beginIndex
*/
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
1-16 concat:字符串拼接
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调用System.arraycopy(),将str的字符数组,从0开始到length,都拷贝到字符数组buf的后面,就实现了连接,底层调用System.arrayCopy */
str.getChars(buf, len);
return new String(buf, true);
}
1-17 replace,替换字符串中的字符
/**
* 替换字符
* @param oldChar 老字符
* @param newChar 新字符
* @return
*/
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) { /* 先找到第一次出现oldChar的位置,这样可以提高字符串中没有oldChar的情况的速度*/
if (val[i] == oldChar) {
break;
}
}
if (i < len) { /* 有oldChar*/
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;
}
1-18 matches(String regex) 匹配字符串是否符合正则表达式
public boolean matches(String regex) {
return Pattern.matches(regex, this);
}
1-19 contains(CharSequence s) 返回是否包含字符串,方法的底层实现是indexOf(s) > -1来判断是否包含指定字符串
1-20 split(String regex,int limit) 分割
1-21 join(String delimetr,CharSequence... elements),第二个参数是可变参数,第一个参数连接符,第二个是字符序列,连接起字符序列后转成字符串。
1-22 各种valueOf方法,将各种类型转换成字符串类型
1-23 trim:去空字符串头部和尾部的空串
/**
* 去掉字符串前后的空字符
* @return
*/
public String trim() {
int len = value.length;
int st = 0;
char[] val = value; /* avoid getfield opcode */
while ((st < len) && (val[st] <= ' ')) { /*去掉头部asc码小于空格的码值(32)*/
st++;
}
while ((st < len) && (val[len - 1] <= ' ')) { /*去掉尾部asc码小于空格的码值(32)*/
len--;
}
return ((st > 0) || (len < value.length)) ? substring(st, len) : this; /*头部或尾部有空格,取子串,否则返回原串*/
}