JDK源码 -- String

一、概念

类定义:

public final class String
    implements java.io.Serializable, Comparable, CharSequence
  • 实现了Serializable接口,可进行序列化。
  • 实现了Comparable接口,可进行比较。
  • 实现了CharSequence接口,说明是个字符序列。

特点:

  • 不可继承。
  • 不可变。
  • 线程安全。

二、使用

//TestString
public class TestString {
    private static final String TAG = "TestString";
    private String str = "tomorrow";

    public void testEquals() {
        Log.d(TAG, "zwm, tomorrow equals tommy: " + str.equals("tommy"));
        Log.d(TAG, "zwm, tomorrow equals tomorrow: " + str.equals("tomorrow"));
    }

    public void testEqualsIgnoreCase() {
        Log.d(TAG, "zwm, tomorrow equalsIgnoreCase TOMORROW: " + str.equalsIgnoreCase("TOMORROW"));
    }

    public void testSubSequence() {
        CharSequence charSequence = str.subSequence(2, 6);
        Log.d(TAG, "zwm, subSequence index 2 - 6: " + charSequence.toString());
    }

    public void testHashCode() {
        Log.d(TAG, "zwm, hashCode: " + str.hashCode());
    }

    public void testStartsWith() {
        Log.d(TAG, "zwm, startsWith tom: " + str.startsWith("tom"));
    }

    public void testStartsWith2() {
        Log.d(TAG, "zwm, startsWith morr index 2: " + str.startsWith("morr", 2));
    }

    public void testEndsWith() {
        Log.d(TAG, "zwm, endsWith rrow: " + str.endsWith("rrow"));
    }

    public void testContains() {
        Log.d(TAG, "zwm, contains morr: " + str.contains("morr"));
    }

    public void testCharAt() {
        Log.d(TAG, "zwm, charAt index 2: " + str.charAt(2));
    }

    public void testCodePointAt() {
        Log.d(TAG, "zwm, codePointAt index 2: " +  str.codePointAt(2));
    }

    public void testCodePointBefore() {
        Log.d(TAG, "zwm, codePointBefore index 2: " +  str.codePointBefore(2));
    }

    public void testCodePointCount() {
        Log.d(TAG, "zwm, codePointCount index 0 - 2: " +  str.codePointCount(0, 2));
    }

    public void testOffsetByCodePoints() {
        Log.d(TAG, "zwm, offsetByCodePoints index 2, offset 1: " +   str.offsetByCodePoints(2, 1));
    }

    public void testCompareTo() {
        Log.d(TAG, "zwm, tomorrow compareTo TOMORROW: " + str.compareTo("TOMORROW"));
    }

    public void testCompareToIgnoreCase() {
        Log.d(TAG, "zwm, tomorrow compareToIgnoreCase TOMORROW: " + str.compareToIgnoreCase("TOMORROW"));
    }

    public void testConcat() {
        Log.d(TAG, "zwm, tomorrow concat XYZ, result: " + str.concat("XYZ"));
        Log.d(TAG, "zwm, tomorrow concat XYZ, str: " + str);
    }

    public void testContentEquals() {
        CharSequence charSequence = "tomorrow";
        Log.d(TAG, "zwm, contentEquals CharSequence: " + str.contentEquals(charSequence));
    }

    public void testContentEquals2() {
        StringBuffer stringBuffer = new StringBuffer("tomorrow");
        Log.d(TAG, "zwm, contentEquals StringBuffer: " + str.contentEquals(stringBuffer));
    }

    public void testGetBytes() {
        Log.d(TAG, "zwm, getBytes size: " + str.getBytes().length);
    }

    public void testGetChars() {
        char[] dest = new char[10];
        str.getChars(2, 6, dest, 0);
        for(int i=0; i<4; i++) {
            Log.d(TAG, "zwm, getChars, ch: " + dest[i]);
        }
    }

    public void testLength() {
        Log.d(TAG, "zwm, length: " + str.length());
    }

    public void testIsEmpty() {
        Log.d(TAG, "zwm, isEmpty: " + str.isEmpty());
    }

    public void testIndexOf() {
        Log.d(TAG, "zwm, indexOf o: " +  str.indexOf('o'));
    }

    public void testLastIndexOf() {
        Log.d(TAG, "zwm, lastIndexOf o: " +  str.lastIndexOf('o'));
    }

    public void testIntern() {
        Log.d(TAG, "zwm, intern: " +  str.intern());
    }

    public void testMatches() {
        boolean result = str.matches(".+omo.+");
        Log.d(TAG, "zwm, match result: " + result);
    }

    public void testRegionMatches() {
        Log.d(TAG, "zwm, tomorrow regionMatches xxtomoxx: " + str.regionMatches(2, "xxtomoxx", 4, 2));
    }

    public void testReplace() {
        String result = str.replace('o', 'p');
        Log.d(TAG, "zwm, tomorrow p replace o, result: " + result);
        Log.d(TAG, "zwm, tomorrow p replace o, str: " + str);
    }

    public void testSplit() {
        String[] result = str.split("o");
        for(String str : result) {
            Log.d(TAG, "zwm, split item: " + str);
        }
        Log.d(TAG, "zwm, split str: " + str);
    }

    public void testSubstring() {
        String result = str.substring(2, 6);
        Log.d(TAG, "zwm, tomorrow substring index 2 - 6, result: " + result);
        Log.d(TAG, "zwm, tomorrow substring index 2 - 6, str: " + str);
    }

    public void testToLowerCase() {
        String result = str.toLowerCase();
        Log.d(TAG, "zwm, toLowerCase, result: " + result);
        Log.d(TAG, "zwm, toLowerCase, str: " + str);
    }

    public void testToUpperCase() {
        String result = str.toUpperCase();
        Log.d(TAG, "zwm, toUpperCase, result: " + result);
        Log.d(TAG, "zwm, toUpperCase, str: " + str);
    }

    public void testToCharArray() {
        char[] result = str.toCharArray();
        for(char ch : result) {
            Log.d(TAG, "zwm, toCharArray ch: " + ch);
        }
    }

    public void testTrim() {
        String test = "  , " + str + " ,  ";
        Log.d(TAG, "zwm, test: " + test  + ", length: " + test.length());
        String result = test.trim();
        Log.d(TAG, "zwm, result: " + result  + ", length: " + result.length());
        Log.d(TAG, "zwm, test: " + test  + ", length: " + test.length());
    }
}

//测试代码
private void testMethod() {
    Log.d(TAG, "zwm, testMethod");
    TestString testString = new TestString();
    testString.testEquals();
    testString.testEqualsIgnoreCase();
    testString.testSubSequence();
    testString.testHashCode();
    testString.testStartsWith();
    testString.testStartsWith2();
    testString.testEndsWith();
    testString.testContains();
    testString.testCharAt();
    testString.testCodePointAt();
    testString.testCodePointBefore();
    testString.testCodePointCount();
    testString.testOffsetByCodePoints();
    testString.testCompareTo();
    testString.testCompareToIgnoreCase();
    testString.testConcat();
    testString.testContentEquals();
    testString.testContentEquals2();
    testString.testGetBytes();
    testString.testGetChars();
    testString.testLength();
    testString.testIsEmpty();
    testString.testIndexOf();
    testString.testLastIndexOf();
    testString.testIntern();
    testString.testMatches();
    testString.testRegionMatches();
    testString.testReplace();
    testString.testSplit();
    testString.testSubstring();
    testString.testToLowerCase();
    testString.testToUpperCase();
    testString.testToCharArray();
    testString.testTrim();
}

//输出log
2019-08-18 17:23:01.983 zwm, testMethod
2019-08-18 17:23:01.985 zwm, tomorrow equals tommy: false
2019-08-18 17:23:01.985 zwm, tomorrow equals tomorrow: true
2019-08-18 17:23:01.986 zwm, tomorrow equalsIgnoreCase TOMORROW: true
2019-08-18 17:23:01.986 zwm, subSequence index 2 - 6: morr
2019-08-18 17:23:01.986 zwm, hashCode: -1037172987
2019-08-18 17:23:01.987 zwm, startsWith tom: true
2019-08-18 17:23:01.987 zwm, startsWith morr index 2: true
2019-08-18 17:23:01.987 zwm, endsWith rrow: true
2019-08-18 17:23:01.987 zwm, contains morr: true
2019-08-18 17:23:01.987 zwm, charAt index 2: m
2019-08-18 17:23:01.987 zwm, codePointAt index 2: 109
2019-08-18 17:23:01.987 zwm, codePointBefore index 2: 111
2019-08-18 17:23:01.987 zwm, codePointCount index 0 - 2: 2
2019-08-18 17:23:01.988 zwm, offsetByCodePoints index 2, offset 1: 3
2019-08-18 17:23:01.988 zwm, tomorrow compareTo TOMORROW: 32
2019-08-18 17:23:01.988 zwm, tomorrow compareToIgnoreCase TOMORROW: 0
2019-08-18 17:23:01.988 zwm, tomorrow concat XYZ, result: tomorrowXYZ
2019-08-18 17:23:01.988 zwm, tomorrow concat XYZ, str: tomorrow
2019-08-18 17:23:01.988 zwm, contentEquals CharSequence: true
2019-08-18 17:23:01.988 zwm, contentEquals StringBuffer: true
2019-08-18 17:23:01.989 zwm, getBytes size: 8
2019-08-18 17:23:01.989 zwm, getChars, ch: m
2019-08-18 17:23:01.989 zwm, getChars, ch: o
2019-08-18 17:23:01.989 zwm, getChars, ch: r
2019-08-18 17:23:01.989 zwm, getChars, ch: r
2019-08-18 17:23:01.989 zwm, length: 8
2019-08-18 17:23:01.989 zwm, isEmpty: false
2019-08-18 17:23:01.989 zwm, indexOf o: 1
2019-08-18 17:23:01.989 zwm, lastIndexOf o: 6
2019-08-18 17:23:01.990 zwm, intern: tomorrow
2019-08-18 17:23:01.990 zwm, match result: true
2019-08-18 17:23:01.990 zwm, tomorrow regionMatches xxtomoxx: true
2019-08-18 17:23:01.990 zwm, tomorrow p replace o, result: tpmprrpw
2019-08-18 17:23:01.990 zwm, tomorrow p replace o, str: tomorrow
2019-08-18 17:23:01.991 zwm, split item: t
2019-08-18 17:23:01.991 zwm, split item: m
2019-08-18 17:23:01.991 zwm, split item: rr
2019-08-18 17:23:01.991 zwm, split item: w
2019-08-18 17:23:01.991 zwm, split str: tomorrow
2019-08-18 17:23:01.991 zwm, tomorrow substring index 2 - 6, result: morr
2019-08-18 17:23:01.991 zwm, tomorrow substring index 2 - 6, str: tomorrow
2019-08-18 17:23:01.991 zwm, toLowerCase, result: tomorrow
2019-08-18 17:23:01.991 zwm, toLowerCase, str: tomorrow
2019-08-18 17:23:01.992 zwm, toUpperCase, result: TOMORROW
2019-08-18 17:23:01.992 zwm, toUpperCase, str: tomorrow
2019-08-18 17:23:01.992 zwm, toCharArray ch: t
2019-08-18 17:23:01.992 zwm, toCharArray ch: o
2019-08-18 17:23:01.992 zwm, toCharArray ch: m
2019-08-18 17:23:01.992 zwm, toCharArray ch: o
2019-08-18 17:23:01.992 zwm, toCharArray ch: r
2019-08-18 17:23:01.992 zwm, toCharArray ch: r
2019-08-18 17:23:01.992 zwm, toCharArray ch: o
2019-08-18 17:23:01.992 zwm, toCharArray ch: w
2019-08-18 17:23:01.993 zwm, test:   , tomorrow ,  , length: 16
2019-08-18 17:23:01.993 zwm, result: , tomorrow ,, length: 12
2019-08-18 17:23:01.993 zwm, test:   , tomorrow ,  , length: 16

三、原理

重要参数

//存放字符串内容的数组
private final char value[];

//hashCode值的缓存
private int hash; // Default to 0

//自定义比较器,可忽略大小写进行字符串的比较
public static final Comparator CASE_INSENSITIVE_ORDER
                                     = new CaseInsensitiveComparator();

构造函数

//无参构造函数
public String() {
    this.value = new char[0]; //创建一个长度为0的新字符数组
}

//指定一个字符串参数的构造函数
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); //拷贝参数中的字符数组生成一个新的字符数组
}

//其它构造函数
...

public int hashCode()

//计算哈希值
public int hashCode() {
    int h = hash; //hash为缓存的哈希值,如果为0则表示未进行缓存
    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 boolean equals(Object anObject)

//判定当前对象与指定的对象是否相等
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 equalsIgnoreCase(String anotherString)

//忽略大小写,判定当前对象与指定的对象是否相等
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;
}

public int compareTo(String anotherString)

//当前对象与指定对象进行比较
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 int compareToIgnoreCase(String str)

//忽略大小写,比较当前字符串与指定的字符串
public int compareToIgnoreCase(String str) {
    return CASE_INSENSITIVE_ORDER.compare(this, str);
}

//自定义比较器
public static final Comparator CASE_INSENSITIVE_ORDER
                                     = new CaseInsensitiveComparator();

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

//CaseInsensitiveComparator
private Object readResolve() { return CASE_INSENSITIVE_ORDER; }

public CharSequence subSequence(int beginIndex, int endIndex)

//从beginIndex索引到endIndex索引构造新字符串
public CharSequence subSequence(int beginIndex, int endIndex) {
    return this.substring(beginIndex, endIndex);
}

public boolean startsWith(String prefix)

//判断当前字符串是否以指定的字符串开头
public boolean startsWith(String prefix) {
    return startsWith(prefix, 0);
}

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 endsWith(String suffix)

//判断当前字符串是否以指定的字符串结尾
public boolean endsWith(String suffix) {
    return startsWith(suffix, value.length - suffix.value.length);
}

public boolean contains(CharSequence s)

//判断当前字符串是否包含指定的字符序列
public boolean contains(CharSequence s) {
    return indexOf(s.toString()) > -1;
}

public char charAt(int index)

//查找索引位置的字符
public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}

public int codePointAt(int index)

//获取索引位置的字符的Unicode码
public int codePointAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return Character.codePointAtImpl(value, index, value.length);
}

//Character
static int codePointAtImpl(char[] a, int index, int limit) {
    char c1 = a[index];
    if (isHighSurrogate(c1) && ++index < limit) {
        char c2 = a[index];
        if (isLowSurrogate(c2)) {
            return toCodePoint(c1, c2);
        }
    }
    return c1;
}

//Character
public static int toCodePoint(char high, char low) {
    // Optimized form of:
    // return ((high - MIN_HIGH_SURROGATE) << 10)
    //         + (low - MIN_LOW_SURROGATE)
    //         + MIN_SUPPLEMENTARY_CODE_POINT;
    return ((high << 10) + low) + (MIN_SUPPLEMENTARY_CODE_POINT
                                   - (MIN_HIGH_SURROGATE << 10)
                                   - MIN_LOW_SURROGATE);
}

public int codePointBefore(int index)

//获取指定索引的前一个位置的字符的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);
}

static int codePointBeforeImpl(char[] a, int index, int start) {
    char c2 = a[--index];
    if (isLowSurrogate(c2) && index > start) {
        char c1 = a[--index];
        if (isHighSurrogate(c1)) {
            return toCodePoint(c1, c2);
        }
    }
    return c2;
}

public int codePointCount(int beginIndex, int endIndex)

//获取beginIndex索引到endIndex索引的Unicode字节码个数
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);
}

static int codePointCountImpl(char[] a, int offset, int count) {
    int endIndex = offset + count;
    int n = count;
    for (int i = offset; i < endIndex; ) {
        if (isHighSurrogate(a[i++]) && i < endIndex &&
            isLowSurrogate(a[i])) {
            n--;
            i++;
        }
    }
    return n;
}

public int offsetByCodePoints(int index, int codePointOffset)

//获取index索引偏移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);
}

//Character
static int offsetByCodePointsImpl(char[]a, int start, int count,
                                  int index, int codePointOffset) {
    int x = index;
    if (codePointOffset >= 0) {
        int limit = start + count;
        int i;
        for (i = 0; x < limit && i < codePointOffset; i++) {
            if (isHighSurrogate(a[x++]) && x < limit &&
                isLowSurrogate(a[x])) {
                x++;
            }
        }
        if (i < codePointOffset) {
            throw new IndexOutOfBoundsException();
        }
    } else {
        int i;
        for (i = codePointOffset; x > start && i < 0; i++) {
            if (isLowSurrogate(a[--x]) && x > start &&
                isHighSurrogate(a[x-1])) {
                x--;
            }
        }
        if (i < 0) {
            throw new IndexOutOfBoundsException();
        }
    }
    return x;
}

public String concat(String 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); //构造新的字符串
}

//构造函数
String(char[] value, boolean share) {
    // assert share : "unshared not supported";
    this.value = value; //将指定的字符数组的地址传递给成员变量value
}

public boolean contentEquals(CharSequence cs)

//当前字符串对象与指定的CharSequence对象进行内容比较
public boolean contentEquals(CharSequence cs) {
    // Argument is a StringBuffer, StringBuilder
    if (cs instanceof AbstractStringBuilder) {
        if (cs instanceof StringBuffer) { //若指定对象是StringBuffer实例,则需要进行同步
            synchronized(cs) {
               return nonSyncContentEquals((AbstractStringBuilder)cs);
            }
        } else {
            return nonSyncContentEquals((AbstractStringBuilder)cs);
        }
    }
    // Argument is a String
    if (cs.equals(this))
        return true;
    // 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;
}

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

public boolean contentEquals(StringBuffer sb)

//当前字符串对象与指定的StringBuffer对象进行内容比较
public boolean contentEquals(StringBuffer sb) {
    return contentEquals((CharSequence)sb);
}

public byte[] getBytes()

//对当前字符串使用默认的字符集获取字节数组
public byte[] getBytes() {
    return StringCoding.encode(value, 0, value.length);
}

//StringCoding
static byte[] encode(char[] ca, int off, int len) {
    String csn = Charset.defaultCharset().name(); //获取默认的字符集
    try {
        // use charset name encode() variant which provides caching.
        return encode(csn, ca, off, len);
    } catch (UnsupportedEncodingException x) {
        warnUnsupportedCharset(csn);
    }
    try {
        return encode("ISO-8859-1", ca, off, len);
    } catch (UnsupportedEncodingException x) {
        // If this code is hit during VM initialization, MessageUtils is
        // the only way we will be able to get any kind of error message.
        MessageUtils.err("ISO-8859-1 charset not available: "
                         + x.toString());
        // If we can not find ISO-8859-1 (a required encoding) then things
        // are seriously wrong with the installation.
        System.exit(1);
        return null;
    }
}

void getChars(char dst[], int dstBegin)

//获取从索引dstBegin开始组成的新字符串
void getChars(char dst[], int dstBegin) {
    System.arraycopy(value, 0, dst, dstBegin, value.length);
}

public int length()

//获取字符串长度
public int length() {
    return value.length;
}

public boolean isEmpty()

//判断字符串是否为空
public boolean isEmpty() {
    return value.length == 0;
}

public int indexOf(int ch)

//从左到右获取第一个与指定字符相同的位置索引
public int indexOf(int ch) {
    return indexOf(ch, 0);
}

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

public int lastIndexOf(int ch)

//从右到左获取第一个与指定字符相同的位置索引
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 boolean matches(String regex)

//判断当前字符串是否匹配指定的正则表达式
public boolean matches(String regex) {
    return Pattern.matches(regex, this);
}

public String replace(char oldChar, char newChar)

//将当前字符串的旧字符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;
}

public String[] split(String regex)

//使用指定的正则表达式分割字符串,并返回分割后的字符串数组
public String[] split(String regex) {
    return split(regex, 0);
}

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 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 substring(int beginIndex, int endIndex)

//从索引beginIndex开始到索引endIndex为止,生成新字符串
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 String toLowerCase()

//将当前字符串转化成小写
public String toLowerCase() {
    return toLowerCase(Locale.getDefault());
}

public String toUpperCase()

//将当前字符串转化成大写
public String toUpperCase() {
    return toUpperCase(Locale.getDefault());
}

public char[] 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;
}

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

public static String format(String format, Object... args)

//格式化输出字符串
public static String format(String format, Object... args) {
    return new Formatter().format(format, args).toString();
}

public static String valueOf(int i)

//将基本类型数据转为字符串数据
public static String valueOf(int i) {
    return Integer.toString(i);
}

public native String intern()

//本地方法
//对于JDK 1.6及之前,当使用intern()方法时,查询字符串常量池是否存在当前字符串,若不存在则将当前字符串复制到字符串常量池中,并返回字符串常量池中的引用。
//对于JDK 1.7及之后,当使用intern()方法时,先查询字符串常量池是否存在当前字符串,若字符串常量池中不存在则再从堆中查询,然后存储并返回相关引用;若都不存在则将当前字符串复制到字符串常量池中,并返回字符串常量池中的引用。
public native String intern();


//例子1
String s = new String("180") + new String("280");
Log.d(TAG, "zwm, s.intern() == s: " + (s.intern() == s));

//输出log
//s指向堆内存字符串地址引用
//s.intern()也指向堆内存字符串地址引用,因为常量池中不存在"180280"字符串地址引用
08-18 15:48:12.401 zwm, s.intern() == s: true


//例子2
String s = new String("181") + new String("281");
Log.d(TAG, "zwm, s == 181281: " + (s == "181281"));
Log.d(TAG, "zwm, s.intern() == s: " + (s.intern() == s));

//输出log
//s指向堆内存字符串地址引用
//由于代码中使用了"181281"字符串,因此常量池中存在一份字符串地址引用
//s.intern()指向常量池字符串地址引用,即非堆内存字符串地址引用
08-18 15:51:41.535 zwm, s == 181281: false
08-18 15:51:41.535 zwm, s.intern() == s: false

四、主题

StringBuffer StringBuilder

你可能感兴趣的:(JDK源码 -- String)