In the preface: The String class is implemented from character arrays. It has multiple schema constructors (null, character array, String, Unicode encoding, ASCII encoding, byte array, etc.), overrides equals, hashCode, etc. In addition to providing methods for converting basic data to String, It also provides a series of methods such as case conversion, character insertion delimiter, character split, include, replace, combine, intercept, compare and so on.
attribute

Value [] Byte array. Cache of hash Hashcode. SerialPersistentFields has no default serialized data.

The constructor

String() creates an empty byte array. String(String original) Assignment array and hash cache. String(char value[]) character array constructor. String(char value[], int offset, int count) interval constructor of character arrays. String(int[] codePoints, int offset, int count) String(byte ASCII [], int hibyte, int offset, Int count) disused constructor String(byte ASCII [], int hibyte) disused constructor String(byte bytes[], int offset, int length, String charsetName) byte constructor, encoding format required, Charset String(byte bytes[], int offset, int length, Charset Charset) String charsetName) byte constructor String(byte bytes[], int offset, Int length) byte constructor String(byte bytes[]) byte constructor String(StringBuffer) String(char[] value, Boolean share) String(char[] value, Boolean share) String(char[] value, Boolean share

Private methods

CheckBounds (byte[] bytes, int offset, int length) Check range nonSyncContentEquals(AbstractStringBuilder SB) : IndexOfSupplementary(int ch, int fromIndex) : Comparison of unicode values lastIndexOfSupplementary(int ch, int fromIndex) : Unicode high and low bits comparison

Internal methods

GetChars (char DST [], int dstBegin) : IndexOf (char[] source, int sourceOffset, int sourceCount,String target, int fromIndex) : IndexOf (char[] source, int sourceOffset, int sourceCount,char[] target, int targetOffset, Int targetCount, int fromIndex) : Indexof (char[] source, int sourceOffset, int sourceCount,char[] target, int targetOffset, Int targetCount,int fromIndex) : look behind the character array subscript

Public methods

CharAt (int index) : takes one of the characters in the character array codePointAt(int index) : CodePointCount (int beginIndex, int endIndex) : Unicode codepoints (int index, int codePointOffset) : GetChars (int srcBegin, int srcEnd, char DST [], int dstBegin) : Copy array getBytes(int srcBegin, int srcEnd, byte DST [], int dstBegin) : Cend has been disabled, copy byte getBytes(String charsetName) : Decode in format getBytes(Charset Charset) : decode in format getBytes() : default decode equals(Object anObject) : comparison method contentEquals(StringBuffer sb) : Comparison method contentEquals(CharSequence cs) : Comparison method equalsIgnoreCase(String anotherString) : Ignore case comparative method compareTo (String anotherString) : compare the subscript compareToIgnoreCase (String STR) : CaseInsensitiveComparator instances of the class. RegionMatches (int toffSet, String Other,int ooffSet,int len) : RegionMatches (Boolean ignoreCase, int toffSet, String Other, int ooffSet, int len) : Ignore the case comparison method startsWith(String prefix, int toffset) : Whether to start the String from the subscript startsWith(String prefix) : EndsWith (String suffix) : endsWith the specified String hashCode() : evaluates when there is no attribute hash indexOf(int ch) : IndexOf(int ch, int fromIndex) : IndexOf(String STR, int fromIndex) : String subindex lastIndexOf(String STR, int fromIndex) : String subindex lastIndexOf(String STR) : LastIndexOf (String STR, int fromIndex) : subString (int beginIndex) : Substring (int beginIndex, int endIndex) : intercepts a String subSequence(int beginIndex, int endIndex) : intercepts a String concat(String STR) : Replace (char oldChar, char newChar) : Replace character matches(String regex) contains(CharSequence S) : Contains the characters replaceFirst(String regex, String replacement) : replaceAll(String regex, String replacement) : Replace (CharSequence target, CharSequence replacement) : replace split(String regex, int limit) : split split(String regex) : Delimiter (CharSequence delimiter, CharSequence… Elements) : Insert characters according to join(CharSequence delimiter,Iterable
elements) : insert characters according to toLowerCase(Locale Locale) : lower case toLowerCase() : lower case toUpperCase(Locale Locale) : Uppercase toUpperCase() : uppercase trim() : trim the front and back Spaces toString() : return the current class toCharArray() : convert the array format(String format, Object… Args: Use the Locale to generate a fixed format(Locale L, String format, Object… Args) : Generates objects in a fixed format intern() string constant pool using a fixed locale

class

CaseInsensitiveComparator: ignore case comparison class

Turn type String

valueOf(Object obj)

valueOf(char data[])

valueOf(char data[], int offset, int count)

copyValueOf(char data[], int offset, int count)

copyValueOf(char data[])

valueOf(boolean b)

valueOf(char c)

valueOf(int i)

valueOf(long l)

valueOf(float f)

valueOf(double d)

// 存储字节数组,即字符串内容
private final char value[];

// 是String hashcode的一个缓存,hashcode进行了重写
private int hash; // Default to 0

// java序列化机制,序列化和反序列化验证版本的一致
private static final long serialVersionUID = -6849794470754667710L;

// 用于指定哪些字段需要被默认序列号,创建一个长度为0的数据,因为String类型的序列化在流处理中是个特例,有自己的序列号逻辑,所以不需要默认序列号
private static final ObjectStreamField[] serialPersistentFields =
    new ObjectStreamField[0];

// 构造函数,定义一个空字符数组给存储字符数组
public String() {
    this.value = new char[0];
}

// 构造函数,赋予字符数组,以及hashcode缓存
public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}

// 构造函数,传参字符数组,重新拷贝这个数组赋予存储字符数组
public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}

// 构造函数,传参字符数组,开始下标,拷贝数量
public String(char value[], int offset, int count) {
    if (offset < 0) {
        throw new StringIndexOutOfBoundsException(offset);
    }
    if (count < 0) {
        throw new StringIndexOutOfBoundsException(count);
    }
    // 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);
}

// 构造函数,codepoints范围:000000 - 10FFFF,代码点:字符的16位Unicode编码,开始下标,拷贝数量
public String(int[] codePoints, int offset, int count) {
    if (offset < 0) {
        throw new StringIndexOutOfBoundsException(offset);
    }
    if (count < 0) {
        throw new StringIndexOutOfBoundsException(count);
    }
    // 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;
}

// ascii编码构造函数,传参ascii数组,补码,开始下标,数量
@Deprecated // 代表已经不用了
public String(byte ascii[], int hibyte, int offset, int count) {
    checkBounds(ascii, offset, count);
    char value[] = new char[count];

    if (hibyte == 0) {
        for (int i = count; i-- > 0;) {
            value[i] = (char)(ascii[i + offset] & 0xff);
        }
    } else {
        hibyte <<= 8;
        for (int i = count; i-- > 0;) {
            value[i] = (char)(hibyte | (ascii[i + offset] & 0xff));
        }
    }
    this.value = value;
}

@Deprecated // 代表已经不用了
public String(byte ascii[], int hibyte) {
    this(ascii, hibyte, 0, ascii.length);
}

// 检查字节数组的范围
private static void checkBounds(byte[] bytes, int offset, int length) {
    if (length < 0)
        throw new StringIndexOutOfBoundsException(length);
    if (offset < 0)
        throw new StringIndexOutOfBoundsException(offset);
    if (offset > bytes.length - length)
        throw new StringIndexOutOfBoundsException(offset + length);
}

// 字节数组构造函数,传参字节数组,开始下标,数量,编码格式charsetName(utf-8),调用方法会转换成Charset
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(utf-8)
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);
}

public String(byte bytes[], String charsetName)
        throws UnsupportedEncodingException {
    this(bytes, 0, bytes.length, charsetName);
}

public String(byte bytes[], Charset charset) {
    this(bytes, 0, bytes.length, charset);
}

// 按默认ISO-8859-1编码格式
public String(byte bytes[], int offset, int length) {
    checkBounds(bytes, offset, length);
    this.value = StringCoding.decode(bytes, offset, length);
}

public String(byte bytes[]) {
    this(bytes, 0, bytes.length);
}

// StringBuffer构造函数,线程不安全,通过同步锁,保证同一个时刻只有一个线程执行
public String(StringBuffer buffer) {
    synchronized(buffer) {
        this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
    }
}

// StringBuilder构造函数
public String(StringBuilder builder) {
    this.value = Arrays.copyOf(builder.getValue(), builder.length());
}

// 直接赋予值数组地址,加个share使用来区分构造函数,无实际意义
String(char[] value, boolean share) {
    // assert share : "unshared not supported";
    this.value = value;
}

// 字符数组长度,utf-16代码单元数量(辅助字符一个代码点是两个代码单元),不一定是实际字符个数
public int length() {
    return value.length;
}

public boolean isEmpty() {
    return value.length == 0;
}

// 取出对应下标的字符
public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}

// 返回指定下标的Unicode代码点
public int codePointAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return Character.codePointAtImpl(value, index, value.length);
}

// 返回指定索引之前的字符Unicode编码
public int codePointBefore(int index) {
    int i = index - 1;
    if ((i < 0) || (i >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return Character.codePointBeforeImpl(value, index, 0);
}

// 返回两个下标之间字符串Unicode的数量,实际的字符个数(代码点数),可以当做length使用
public int codePointCount(int beginIndex, int endIndex) {
    if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) {
        throw new IndexOutOfBoundsException();
    }
    return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
}

// 返回从下标开始偏移codePointOffset个代码点的索引
public int offsetByCodePoints(int index, int codePointOffset) {
    if (index < 0 || index > value.length) {
        throw new IndexOutOfBoundsException();
    }
    return Character.offsetByCodePointsImpl(value, 0, value.length,
            index, codePointOffset);
}

// 将字符数组从下标0开始拷贝到目标数组中
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) {
        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);
}

@Deprecated // 不再使用
public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {
    if (srcBegin < 0) {
        throw new StringIndexOutOfBoundsException(srcBegin);
    }
    if (srcEnd > value.length) {
        throw new StringIndexOutOfBoundsException(srcEnd);
    }
    if (srcBegin > srcEnd) {
        throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
    }
    Objects.requireNonNull(dst);

    int j = dstBegin;
    int n = srcEnd;
    int i = srcBegin;
    char[] val = value;   /* avoid getfield opcode */

    while (i < n) {
        dst[j++] = (byte)val[i++];
    }
}

// 按照编码格式进行编码
public byte[] getBytes(String charsetName)
        throws UnsupportedEncodingException {
    if (charsetName == null) throw new NullPointerException();
    return StringCoding.encode(charsetName, value, 0, value.length);
}

// 按照编码格式进行编码
public byte[] getBytes(Charset charset) {
    if (charset == null) throw new NullPointerException();
    return StringCoding.encode(charset, value, 0, value.length);
}

// 按默认ISO-8859-1编码格式
public byte[] getBytes() {
    return StringCoding.encode(value, 0, value.length);
}

// 判断地址,判断类型,判断长度,循环比较
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        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;
}

// 转成字符序列比较
public boolean contentEquals(StringBuffer sb) {
    return contentEquals((CharSequence)sb);
}

// 字符序列是AbstractStringBuilder的之类比较,比较长度,循环比较
private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
    char v1[] = value;
    char v2[] = sb.getValue();
    int n = v1.length;
    if (n != sb.length()) {
        return false;
    }
    for (int i = 0; i < n; i++) {
        if (v1[i] != v2[i]) {
            return false;
        }
    }
    return true;
}

// 比较字符序列方法,AbstractStringBuilder比较,String比较,判断长度,代码点比较
public boolean contentEquals(CharSequence cs) {
    // Argument is a StringBuffer, StringBuilder
    if (cs instanceof AbstractStringBuilder) {
        if (cs instanceof StringBuffer) {
            synchronized(cs) {
               return nonSyncContentEquals((AbstractStringBuilder)cs);
            }
        } else {
            return nonSyncContentEquals((AbstractStringBuilder)cs);
        }
    }
    // Argument is a String
    if (cs instanceof String) {
        return equals(cs);
    }
    // Argument is a generic CharSequence
    char v1[] = value;
    int n = v1.length;
    if (n != cs.length()) {
        return false;
    }
    for (int i = 0; i < n; i++) {
        if (v1[i] != cs.charAt(i)) {
            return false;
        }
    }
    return true;
}

// 比较地址,比较长度、不考虑大小写比较
public boolean equalsIgnoreCase(String anotherString) {
    return (this == anotherString) ? true
            : (anotherString != null)
            && (anotherString.value.length == value.length)
            && regionMatches(true, 0, anotherString, 0, value.length);
}

// 比较字符内容,如果不等,返回字符ascii码差值,相等,返回长度差值
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;
}

// 根据比较类创建一个对象,引用不可变,内容可变
public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                     = new CaseInsensitiveComparator();
									 
// 字符串比较类,如果字符或大写或小写只要有个相同就遍历下一个,否则返回两个ascii的差值
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; }
}

// 当前字符串和参数比较
public int compareToIgnoreCase(String str) {
    return CASE_INSENSITIVE_ORDER.compare(this, str);
}

// 和参数比较在各自区域内是否相等
public boolean regionMatches(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) {
        if (ta[to++] != pa[po++]) {
            return false;
        }
    }
    return true;
}

// 是否开启忽略大小写的区域比较
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;
}

// 从下标开始,是否以参数开头
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);
}

public boolean endsWith(String suffix) {
    return startsWith(suffix, value.length - suffix.value.length);
}

// hashcode的计算方式,已计算的放入缓存
public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}


public int indexOf(int ch) {
    return indexOf(ch, 0);
}

// 检测范围,进行比较,Unicode字符,返回开始下标
public int indexOf(int ch, int fromIndex) {
    final int max = value.length;
    if (fromIndex < 0) {
        fromIndex = 0;
    } else if (fromIndex >= max) {
        // Note: fromIndex might be near -1>>>1.
        return -1;
    }
	//最小代码点,直接比较值,一字节
    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++) {
            if (value[i] == ch) {
                return i;
            }
        }
        return -1;
    } else {
        return indexOfSupplementary(ch, fromIndex);
    }
}

// Unicode字符高低位比较,2字节
private int indexOfSupplementary(int ch, int fromIndex) {
    if (Character.isValidCodePoint(ch)) {
        final char[] value = this.value;
        final char hi = Character.highSurrogate(ch);
        final char lo = Character.lowSurrogate(ch);
        final int max = value.length - 1;
        for (int i = fromIndex; i < max; i++) {
            if (value[i] == hi && value[i + 1] == lo) {
                return i;
            }
        }
    }
    return -1;
}

// 反着找下标
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);
    }
}

// Unicode字符高低位比较,2字节
private int lastIndexOfSupplementary(int ch, int fromIndex) {
    if (Character.isValidCodePoint(ch)) {
        final char[] value = this.value;
        char hi = Character.highSurrogate(ch);
        char lo = Character.lowSurrogate(ch);
        int i = Math.min(fromIndex, value.length - 2);
        for (; i >= 0; i--) {
            if (value[i] == hi && value[i + 1] == lo) {
                return i;
            }
        }
    }
    return -1;
}

// 返回下标
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);
}

// 实现方法,如果开始下标大于等于源数组数量,如果目标数组数量等于0返回,不然返回-1,先判断第一个,再判断后面字符
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);

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

// 倒着查最后出现的
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,
        String target, int fromIndex) {
    return lastIndexOf(source, sourceOffset, sourceCount,
                   target.value, 0, target.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.
     */
    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;

startSearchForLastChar:
    while (true) {
        while (i >= min && source[i] != strLastChar) {
            i--;
        }
        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;
            }
        }
        return start - sourceOffset + 1;
    }
}

// 从开始下标截取字符串
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);
}

// 返回类型区分
public CharSequence subSequence(int beginIndex, int endIndex) {
    return this.substring(beginIndex, endIndex);
}

// 组合字符串
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);
}

// 替换字符,返回新字符串,过滤相等的,再进行判断
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;
}

// 根据正则表达式判断是否匹配((.*)值(.*))
public boolean matches(String regex) {
    return Pattern.matches(regex, this);
}

// 是否包含
public boolean contains(CharSequence s) {
    return indexOf(s.toString()) > -1;
}

// 根据正则表达式替换首次出现的,成功则返回替换的字符串,失败则返回原始字符串。
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()));
}

// 根据正则表达式进行拆分,参数拆分正则表达式、返回数组最大长度,验证分割规则,防止未转义和编码错误,验证长度进行截取放入数组,根据限制长度未分割的放至最后一个,最后去除空格的
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);
}

// 在字符串里面插入分隔符,可变参数
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 String toString() {
    return 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();
}

// 使用指定语言环境,制定字符串格式和参数生成格式化字符串
public static String format(Locale l, String format, Object... args) {
    return new Formatter(l).format(format, args).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);
}

// 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();
Copy the code