完整路径:java.lang.String
- 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;
- 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对象返回