Java string的源码感悟

package java.lang;

public final class String

implements java.io.Serializable, Comparable , CharSequence {

复制代码
// 核心:字符数组,存储字符串内容
private final char value[];

// 缓存哈希值,默认 0
private int hash;

// 序列化版本号
private static final long serialVersionUID = -6849794470754667710L;

// 空字符串构造
public String() {
    this.value = "".value;
}
public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}
public String(char value[]) {
    this.value = java.util.Arrays.copyOf(value, value.length);
}
public int length() {
    return value.length;
}
public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}
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  substring(int beginIndex) {
    int subLen = value.length - beginIndex;
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    int len = value.length;
    char buf[] = new char[len + otherLen];
    System.arraycopy(value, 0, buf, 0, len);
    str.getChars(buf, len);
    return new String(buf, true);
}
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;
}

}

源码中 String 被 final 修饰、底层存储字符的 char[] value 也被 private final 修饰,双重限制让字符串一旦创建就无法修改。我们日常使用的 substring() 、 concat() 、 replace() 等看似修改字符串的方法,本质都不是修改原对象,而是新建一个字符串对象并返回。

这让我明白:Java中字符串"修改"只是表象,底层永远是新建对象,这也是频繁拼接字符串不建议直接用 + ,要使用 StringBuilder 的根本原因。