JDK1.8源码解析——String

String源码分析

一:类的声明

在java.lang包中,此类被final修饰,表示String的对象是不可变量,不可继承。
String类实现了Serizlizable,Comparable, CharSequence接口。
Serizlizable接口没有任何方法和域,仅用于标识序列化的语意,实现此接口的类是可序列化的,是java提供的通用数据保存和读取的接口。
Comparable接口只有一个compareTo(To)方法。
这里写图片描述
CharSequence接口如下图
这里写图片描述

类的成员变量

/** The value is used for character storage. */
private final char value[]; //使用字符数组存放字符串

/** Cache the hash code for the string */
private int hash; // Default to 0  存放哈希值

类的构造方法

无参构造器

// 无参构造方法 因为String对象内容不可变,所以没有必要调用此方法。
public String() {
    this.value = "".value;
}

String 参数

//初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}

可以看到只是将value引用指向original中的value数组,因为两者都是final的,所以这个看来也没那么必要。因为String s1=new String(“s1s1”); String s2=new String(s1);这种用法完全没有必要,而不如直接引用,s2=s1;

char[]参数

// 分配一个新的 String,使其表示字符数组参数中当前包含的字符序列。
public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}
//可以发现当通过char数组构建时,只是将char数组复制到value中,而且是复制,而不是简单的引用相等。

// 分配一个新的 String,它包含取自字符数组参数一个子数组的字符。
// offset是起始位置,count是字符数量
public String(char value[], int offset, int count) {    
    if (offset < 0) { // 如果起始位置小于0
        throw new StringIndexOutOfBoundsException(offset);
    }
    if (count <= 0) { // 如果字符数量小于1
        if (count < 0) { // 如果字符数量小于0
            throw new StringIndexOutOfBoundsException(count);
        }
        if (offset <= value.length) { // 如果起始位置不超过参数中字符数组长度
            this.value = "".value; // 设置为空字符串
            return;
        }
    }
    // Note: offset or count might be near -1>>>1.
    if (offset > value.length - count) { // 如果起始位置与字符数量不符合逻辑
        throw new StringIndexOutOfBoundsException(offset + count);
    }

    // 创建字符数组副本
    this.value = Arrays.copyOfRange(value, offset, offset+count);
}
与上面的区别是,这里只是利用char数组中的一部分来构建String,其中offset代表起始下标,count是所有构建的长度。

int[]参数

//分配一个新的 String,它包含 Unicode 代码点数组参数一个子数组的字符。
public String(int[] codePoints, int offset, int count) {
    if (offset < 0) {
        throw new StringIndexOutOfBoundsException(offset);
    }
    if (count <= 0) {
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        if (offset <= codePoints.length) {
            this.value = "".value;
            return;
        }
    }
    // Note: offset or count might be near -1>>>1.
    if (offset > codePoints.length - count) {
        throw new StringIndexOutOfBoundsException(offset + count);
    }

    final int end = offset + count;

    // Pass 1: Compute precise size of char[]
    int n = count;
    for (int i = offset; i < end; i++) {
        int c = codePoints[i];
        if (Character.isBmpCodePoint(c))
            continue;
        else if (Character.isValidCodePoint(c))
            n++;
        else throw new IllegalArgumentException(Integer.toString(c));
    }

    // Pass 2: Allocate and fill in char[]
    final char[] v = new char[n];

    for (int i = offset, j = 0; i < end; i++, j++) {
        int c = codePoints[i];
        if (Character.isBmpCodePoint(c))
            v[j] = (char)c;
        else
            Character.toSurrogates(c, v, j++);
    }

    this.value = v;
}

byte[]参数

所谓好的适用性模块,一定是能有一坨坨的各种适应代码的。下面是一系列的利用byte[]数组来构建String对象的构造器,主要差别是可能需要指定特殊的字符集来解码,但是这一点其实在web编程,网络编程中还是很重要的

//通过使用指定的字符集解码指定的 byte 子数组,构造一个新的 String。
public String(byte bytes[], int offset, int length, String charsetName)
        throws UnsupportedEncodingException {
    if (charsetName == null)
        throw new NullPointerException("charsetName");
    checkBounds(bytes, offset, length);
    this.value = StringCoding.decode(charsetName, bytes, offset, length);
}

//通过使用指定的 charset 解码指定的 byte 子数组,构造一个新的 String。
public String(byte bytes[], int offset, int length, Charset charset) {
    if (charset == null)
        throw new NullPointerException("charset");
    checkBounds(bytes, offset, length);
    this.value =  StringCoding.decode(charset, bytes, offset, length);
}

// 通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
public String(byte bytes[], String charsetName)
        throws UnsupportedEncodingException {
    this(bytes, 0, bytes.length, charsetName);
}

//通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
public String(byte bytes[], Charset charset) {
    this(bytes, 0, bytes.length, charset);
}

//通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。
public String(byte bytes[], int offset, int length) {
    checkBounds(bytes, offset, length);
    this.value = StringCoding.decode(bytes, offset, length);
}

//通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
public String(byte bytes[]) {
    this(bytes, 0, bytes.length);
}

基于StringBuilder,StringBuffer参数

//分配一个新的字符串,它包含字符串缓冲区参数中当前包含的字符序列。
public String(StringBuffer buffer) {
    synchronized(buffer) {
        this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
    }
}

//分配一个新的字符串,它包含字符串生成器参数中当前包含的字符序列。
public String(StringBuilder builder) {
    this.value = Arrays.copyOf(builder.getValue(), builder.length());
}

String(char[] value, boolean share) {
    // assert share : "unshared not supported";
    this.value = value;
}

重要方法

length

//获取字符串长度
//返回字符串中所包含的字符数目,即value数组的长度
public int length() {
    return value.length;
}

isEmpty

// 判断字符串是否为空
// 判断字符串是否为空,即判断value数组的长度为0即可
public boolean isEmpty() {
    return value.length == 0;
}

charAt

//按下标获取单个字符
//返回指定索引处的 char 值。索引范围为从 0 到 length() - 1。序列的第一个 char 值位于索引 0 处,第二个位于索引 1 处,依此类推,这类似于数组索引。 
public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}

getChars

//将字符串拷贝到目标字符数组
void getChars(char dst[], int dstBegin) {
    System.arraycopy(value, 0, dst, dstBegin, value.length);
}

// 获取子串,把它拷贝到目标字符数组
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
    if (srcBegin < 0) { // 如果源数组开始位置<0
        throw new StringIndexOutOfBoundsException(srcBegin);
    }
    if (srcEnd > value.length) { // 如果源数组结束位置>字符数组长度
        throw new StringIndexOutOfBoundsException(srcEnd);
    }
    if (srcBegin > srcEnd) { // 如果源数组开始位置>源数组结束位置
        throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
    }
    System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}

getBytes

//使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 
public byte[] getBytes(String charsetName)
        throws UnsupportedEncodingException {
    if (charsetName == null) throw new NullPointerException();
    return StringCoding.encode(charsetName, value, 0, value.length);
}

//使用给定的 charset 将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。 
public byte[] getBytes(Charset charset) {
    if (charset == null) throw new NullPointerException();
    return StringCoding.encode(charset, value, 0, value.length);
}

//使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 
public byte[] getBytes() {
    return StringCoding.encode(value, 0, value.length);
}

equals

//将此字符串与指定的对象比较。当且仅当该参数不为 null,并且是与此对象表示相同字符序列的 String 对象时,结果才为 true。 
//比较两个引用指向的String对象内容是否相同
public boolean equals(Object anObject) {
    if (this == anObject) { // 如果两个引用指向的是同一个String对象
        return true;
    }
    if (anObject instanceof String) { // 如果第2个引用指向的对象是String实例
        String anotherString = (String)anObject; // 强制类型转换
        int n = value.length; // 获取第1个引用指向的String对象的字符串长度
        if (n == anotherString.value.length) { // 如果两个字符串长度相等
            // 定义字符数组指针
            char v1[] = value; 
            char v2[] = anotherString.value;

            // 字符依次比较
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

可以看到equals方法重写了,会判断两个字符串的每一个字符是否相等。

equalsIgnoreCase

//将此 String 与另一个 String 比较,不考虑大小写。如果两个字符串的长度相同,并且其中的相应字符都相等(忽略大小写),则认为这两个字符串是相等的。
public boolean equalsIgnoreCase(String anotherString) {
        return (this == anotherString) ? true
                : (anotherString != null)
                && (anotherString.value.length == value.length)
                && regionMatches(true, 0, anotherString, 0, value.length);
    }
    判断两个字符串在忽略大小写的情况下是否相等,主要调用regionMatches方法

    public boolean regionMatches(boolean ignoreCase, int toffset,
            String other, int ooffset, int len) {
        char ta[] = value;
        int to = toffset;
        char pa[] = other.value;
        int po = ooffset;
        // Note: toffset, ooffset, or len might be near -1>>>1.
        if ((ooffset < 0) || (toffset < 0)
                || (toffset > (long)value.length - len)
                || (ooffset > (long)other.value.length - len)) {
            return false;
        }
        while (len-- > 0) {
            char c1 = ta[to++];
            char c2 = pa[po++];
            //在这里先行判断,如果相等就直接跳过后面即可,可以提高效率
            if (c1 == c2) {
                continue;
            }
            if (ignoreCase) {
                // If characters don't match but case may be ignored,
                // try converting both characters to uppercase.
                // If the results match, then the comparison scan should
                // continue.
                char u1 = Character.toUpperCase(c1);
                char u2 = Character.toUpperCase(c2);
                //都转换成大写的形式,如果相等,则跳过
                if (u1 == u2) {
                    continue;
                }
                // Unfortunately, conversion to uppercase does not work properly
                // for the Georgian alphabet, which has strange rules about case
                // conversion.  So we need to make one last check before
                // exiting.
                if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
                    continue;
                }
            }
            return false;
        }
        return true;
    }

compareTo

// 比较两个String对象的大小
public int compareTo(String anotherString) {
    // 获取字符数组长度
    int len1 = value.length;
    int len2 = anotherString.value.length;
    // 获取最小长度
    int lim = Math.min(len1, len2);
    // 定义字符数组指针
    char v1[] = value;
    char v2[] = anotherString.value;

    int k = 0;
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        if (c1 != c2) { // 如果两个字符不相等
            return c1 - c2;
        }
        k++;
    }

    // 根据长度比较大小
    return len1 - len2;
}

比较两个字符串的大小。如果两个字符串的字符序列相等,则返回0;不相等时,从两个字符串第0个字符开始比较,返回第一个不相等的字符差。另一种情况,较长的字符串的前面部分恰好是较短的字符串,则返回他们的长度差。

startsWith

//测试此字符串从指定索引开始的子字符串是否以指定前缀开始。
public boolean startsWith(String prefix, int toffset) {
    char ta[] = value;
    int to = toffset;
    char pa[] = prefix.value;
    int po = 0;
    int pc = prefix.value.length;
    // Note: toffset might be near -1>>>1.
    if ((toffset < 0) || (toffset > value.length - pc)) {
        return false;
    }
    while (--pc >= 0) {
        if (ta[to++] != pa[po++]) {
            return false;
        }
    }
    return true;
}

//测试此字符串是否以指定的前缀开始。 
public boolean startsWith(String prefix) {
    return startsWith(prefix, 0);
}

endsWith

//测试此字符串是否以指定的后缀结束。
public boolean endsWith(String suffix) {
    return startsWith(suffix, value.length - suffix.value.length);
}

hashCode

//返回此字符串的哈希码。String 对象的哈希码根据以下公式计算: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] 使用 int 算法,这里 s[i] 是字符串的第 i 个字符,n 是字符串的长度,^ 表示求幂。(空字符串的哈希值为 0。) 
// 获取散列码方法
public int hashCode() {
    // 获取字符串缓存散列码
    int h = hash;
    if (h == 0 && value.length > 0) { // 如果字符串缓存散列码为0并且字符串数组长度大于0
        // 定义字符数组指针
        char val[] = value;

        // 遍历每个字符
        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i]; // 31 * h会被JVM优化成(h << 5) - h
        }
        hash = h; // 修改字符串缓存散列码
    }
    return h;
}

indexOf

// 获取指定字符在此字符串中第一次出现处的索引
public int indexOf(int ch) {
    return indexOf(ch, 0); // 从0开始查找
}

// 获取在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索。
// Unicode指统一码(采用双字节对字符进行编码)
public int indexOf(int ch, int fromIndex) {
    // 获取字符数组长度
    final int max = value.length;
    if (fromIndex < 0) { // 如果起始位置<0
        fromIndex = 0; // 起始位置置0
    } else if (fromIndex >= max) { // 如果起始位置>=字符数组长度
        // Note: fromIndex might be near -1>>>1.
        return -1;
    }

    // Character.MIN_SUPPLEMENTARY_CODE_POINT是BmpCode代码点
    // 值是2的16次方,是2个字节最大值+1
    // 如果ch是非辅助代码点或者负值(无效代码点)
    if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { 
        // handle most cases here (ch is a BMP code point or a
        // negative value (invalid code point))
        final char[] value = this.value; // 创建字符数组的指针
        for (int i = fromIndex; i < max; i++) { // 从fromIndex开始遍历每个字符
            if (value[i] == ch) { // 如果找到ch字符
                return i;
            }
        }
        return -1;
    } else { // 寻找ch在辅助部分中的索引
        return indexOfSupplementary(ch, fromIndex);
    }
}

//返回指定字符在此字符串中最后一次出现处的索引。
public int lastIndexOf(int ch) {
    return lastIndexOf(ch, value.length - 1);
}

//返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索。
public int lastIndexOf(int ch, int fromIndex) {
    if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
        // handle most cases here (ch is a BMP code point or a
        // negative value (invalid code point))
        final char[] value = this.value;
        int i = Math.min(fromIndex, value.length - 1);
        for (; i >= 0; i--) {
            if (value[i] == ch) {
                return i;
            }
        }
        return -1;
    } else {
        return lastIndexOfSupplementary(ch, fromIndex);
    }
}

//返回指定子字符串在此字符串中第一次出现处的索引。
public int indexOf(String str) {
    return indexOf(str, 0);
}

//返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
public int indexOf(String str, int fromIndex) {
    return indexOf(value, 0, value.length,
            str.value, 0, str.value.length, fromIndex);
}


// 获取参数子串在该字符串中从起始位置开始第一次出现的位置
static int indexOf(char[] source, int sourceOffset, int sourceCount,
        String target, int fromIndex) {
    return indexOf(source, sourceOffset, sourceCount,
                   target.value, 0, target.value.length,
                   fromIndex);
}

/* @param   source       the characters being searched.//这里就是value数组
     * @param   sourceOffset offset of the source string./ //源字符串的偏移量
     * @param   sourceCount  count of the source string.    //这里是value数组的长度
     * @param   target       the characters being searched for.  //待搜索目标字符串
     * @param   targetOffset offset of the target string.   //待搜索目标字符串的偏移量
     * @param   targetCount  count of the target string.   //待搜索目标字符串的长度
     * @param   fromIndex    the index to begin searching from. //起始位置
     */
    // 获取参数子串在该字符串中从起始位置开始第一次出现的位置
    // source是目标串(该字符串),target是模式串(子串)
    static int indexOf(char[] source, int sourceOffset, int sourceCount,
        char[] target, int targetOffset, int targetCount,
        int fromIndex) {
        if (fromIndex >= sourceCount) {//越界了
            return (targetCount == 0 ? sourceCount : -1);
        }
        if (fromIndex < 0) {
            fromIndex = 0;
        }
        if (targetCount == 0) {
            return fromIndex;
        }

        char first = target[targetOffset];//待搜索字符串第一个字符
        int max = sourceOffset + (sourceCount - targetCount);//搜索第一个匹配的字符时所能达到的最大值,因为要保证后面的长度>=targetCount

        // 朴素匹配算法
        //下面这里就是核心搜索算法了,会先匹配第一个字符,然后依次向后移,直到完全匹配
        //或者是匹配到max仍然没有匹配成功
        for (int i = sourceOffset + fromIndex; i <= max; i++) {
            /* Look for first character. */
            if (source[i] != first) {// 如果第一个字符不匹配
                while (++i <= max && source[i] != first);// 寻找第一个匹配上的字符
            }

            /* Found first character, now look at the rest of v2 */
            //可以注意这里i下标只是用来匹配第一个字符,因为有可能部分匹配时,需要从先在匹配
            //所以这里重新应用下标j
            if (i <= max) {// 匹配除了第一个字符的其他部分
                int j = i + 1;
                int end = j + targetCount - 1;
                for (int k = targetOffset + 1; j < end && source[j]
                        == target[k]; j++, k++);

                if (j == end) {
                    /* Found whole string. */
                    return i - sourceOffset;
                }
            }
        }
        return -1;
    }//当匹配失败时,返回-1

//返回指定子字符串在此字符串中最右边出现处的索引。
public int lastIndexOf(String str) {
    return lastIndexOf(str, value.length);
}


public int lastIndexOf(String str, int fromIndex) {
    return lastIndexOf(value, 0, value.length,
            str.value, 0, str.value.length, fromIndex);
}

static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
/*
* Check arguments; return immediately where possible. For
* consistency, don’t check for null str.
*/
//第一个字符所能匹配的最大位置,类似于上面的max
int rightIndex = sourceCount - targetCount;
if (fromIndex < 0) {
return -1;
}
if (fromIndex > rightIndex) {
fromIndex = rightIndex;
}
/* Empty string always matches. */
if (targetCount == 0) {
return fromIndex;
}

            int strLastIndex = targetOffset + targetCount - 1;//目标字符串最后一个字符下标
            char strLastChar = target[strLastIndex];//最后一个字符
            int min = sourceOffset + targetCount - 1;//目标字符串最后一个字符所能匹配的源字符串最小下标
            int i = min + fromIndex;//这里i下标永远是最后一个字符匹配的下标索引

        startSearchForLastChar:
            while (true) {
                while (i >= min && source[i] != strLastChar) {
                    i--;
                }
                //小于min则不可能在搜索到了
                if (i < min) {
                    return -1;
                }
                int j = i - 1;
                int start = j - (targetCount - 1);
                int k = strLastIndex - 1;

                while (j > start) {
                    if (source[j--] != target[k--]) {
                        //当存在部分匹配,而前半部分不匹配时,跳出当前查找,整体向前窗移
                        i--;
                        continue startSearchForLastChar;//直接跳到顶层while循环
                    }
                }
                return start - sourceOffset + 1;
            }
        }

可以看到与indexOf方法是对应的,只不过是反向搜索。

substring

//返回一个新的字符串,它是此字符串的一个子字符串。该子字符串从指定索引处的字符开始,直到此字符串末尾。
public String substring(int beginIndex) {
    if (beginIndex < 0) { // 如果起始下标<0
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    int subLen = value.length - beginIndex; // 获取截取长度
    if (subLen < 0) { // 如果截取长度<0
        throw new StringIndexOutOfBoundsException(subLen);
    }
    return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

//返回一个新字符串,它是此字符串的一个子字符串。该子字符串从指定的 beginIndex 处开始,直到索引 endIndex - 1 处的字符。因此,该子字符串的长度为 endIndex-beginIndex。 
public String substring(int beginIndex, int endIndex) {
    if (beginIndex < 0) { // 如果起始下标<0
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > value.length) { // 如果末尾下标>字符数组长度
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    int subLen = endIndex - beginIndex; // 获取截取长度
    if (subLen < 0) { // 如果截取长度<0
        throw new StringIndexOutOfBoundsException(subLen);
    }
    return ((beginIndex == 0) && (endIndex == value.length)) ? this
            : new String(value, beginIndex, subLen);
}

concat

//将指定字符串连接到此字符串的结尾。 
//如果参数字符串的长度为 0,则返回此 String 对象。否则,创建一个新的 String 对象,用来表示由此 String 对象表示的字符序列和参数字符串表示的字符序列连接而成的字符序列。
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);
}

void getChars(char dst[], int dstBegin) {
            System.arraycopy(value, 0, dst, dstBegin, value.length);
    }

replace

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;
}

matches

//告知此字符串是否匹配给定的正则表达式。
public boolean matches(String regex) {
    return Pattern.matches(regex, this);
}

split

//根据给定正则表达式的匹配拆分此字符串。 
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);
}

public String[] split(String regex) {
    return split(regex, 0);
}

trim

//返回字符串的副本,忽略前导空白和尾部空白。
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;
}

这个trim()是去掉首尾的空格,而实现方式也非常简单,分别找到第一个非空格字符的下标,与最后一个非空格字符的下标
然后返回之间的子字符串。注意这里由于应用了substring方法,所以len变量的控制要小心

toString

//获取当前String对象
public String toString() {
    return this;
}

toCharArray

//将此字符串转换为一个新的字符数组。 
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;
}

format

//使用指定的格式字符串和参数返回一个格式化字符串。
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();
}

valueOf

//返回 Object 参数的字符串表示形式。
public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

//返回 char 数组参数的字符串表示形式。字符数组的内容已被复制,后续修改不会影响新创建的字符串。 
public static String valueOf(char data[]) {
    return new String(data);
}

//返回 char 数组参数的特定子数组的字符串表示形式。 
//offset 参数是子数组的第一个字符的索引。count 参数指定子数组的长度。字符数组的内容已被复制,后续修改不会影响新创建的字符串。 
public static String valueOf(char data[], int offset, int count) {
    return new String(data, offset, count);
}

//返回指定数组中表示该字符序列的 String。 
public static String copyValueOf(char data[], int offset, int count) {
    return new String(data, offset, count);
}

//返回指定数组中表示该字符序列的 String。 
public static String copyValueOf(char data[]) {
    return new String(data);
}

//返回 boolean 参数的字符串表示形式。 
public static String valueOf(boolean b) {
    return b ? "true" : "false";
}

//返回 char 参数的字符串表示形式。 
public static String valueOf(char c) {
    char data[] = {c};
    return new String(data, true);
}

//返回 int 参数的字符串表示形式。 
public static String valueOf(int i) {
    return Integer.toString(i);
}

//返回 long 参数的字符串表示形式。 
public static String valueOf(long l) {
    return Long.toString(l);
}

//返回 float 参数的字符串表示形式。 
public static String valueOf(float f) {
    return Float.toString(f);
}

//返回 double 参数的字符串表示形式。 
public static String valueOf(double d) {
    return Double.toString(d);
}

//本地方法,把该字符串存入常量池,返回此字符串的引用
public native String intern();

猜你喜欢

转载自blog.csdn.net/wangyuanjun008/article/details/79233411