String

25 阅读2分钟

完整路径:java.lang.String

  1. String内部的字段
// 此字段是常量,用Stable注解标记表示一旦String构造完成之后不会再改变
@Stable
private final byte[] value;

// 对value字段中的字节进行编码的标识符
private final byte coder;

// 缓存hashCode()方法计算出来的值
private int hash; // Default to 0

// 如果hashCode方法计算出的是0,则缓存,避免重复计算
private boolean hashIsZero; // Default to false;

// 序列化id
@java.io.Serial
private static final long serialVersionUID = -6849794470754667710L;
// 是否启用字符串压缩,如果不启用,则value字段中的字节始终以UTF-16编码。
static final boolean COMPACT_STRINGS;

  1. String的常用方法
//这是String的构造方法,这里根据charset的不同以及其它条件,对bytes进行解码,然后设置到value字段
public String(byte[] bytes, int offset, int length, Charset charset) {
    Objects.requireNonNull(charset);
    checkBoundsOffCount(offset, length, bytes.length);
    if (length == 0) {
        this.value = "".value;
        this.coder = "".coder;
    } else if (charset == UTF_8.INSTANCE) {
        if (COMPACT_STRINGS && !StringCoding.hasNegatives(bytes, offset, length)) {
            this.value = Arrays.copyOfRange(bytes, offset, offset + length);
            this.coder = LATIN1;
        } else {
    // 省略部分代码
        }
    } else if (charset == ISO_8859_1.INSTANCE) {
    // 省略部分代码
    } else if (charset == US_ASCII.INSTANCE) {
            // 省略部分代码
        }
    } else {
        if (cd instanceof ArrayDecoder ad) {
            // 省略部分代码
        }
        // 省略部分代码
    }
}

// 用来比较该字符串和指定的对象,首先判断是否String类型,然后判断是够被压缩或者2个比较的String的coder是否相同,然后比较2个字符串的value字段
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    return (anObject instanceof String aString)
            && (!COMPACT_STRINGS || this.coder == aString.coder)
            && StringLatin1.equals(value, aString.value);
}

// 返回一个子字符串,子字符串从指定的beginIndex开始,并扩展到索引endIndex-1处的字符,且返回的是一个新的字符串
public String substring(int beginIndex, int endIndex) {
    int length = length();
    checkBoundsBeginEnd(beginIndex, endIndex, length);
    if (beginIndex == 0 && endIndex == length) {
        return this;
    }
    int subLen = endIndex - beginIndex;
    return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
                      : StringUTF16.newString(value, beginIndex, subLen);
}

总结: String是不可变的,要想修改String的内容只能生成一个新的String对象返回