1.String
String类的基本字段(field)
Java9之后,String中用byte[]存储字符串,并用coder表示该字符串使用哪种编码。
coder主要是为了适应不同语言字符的需要,有的字符需要2字节编码,有的只需要1字节,coder就表示这个字符串应当使用哪种编码规则。这样在存储像英文一样只需要一个字节的字符时,可以压缩空间。coder有LATIN1(1字节)和UTF16(2字节)两种选项,相关的还有COMPACT_STRINGS,为true表示这个字符串是压缩的。编码这块由JVM处理。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final byte[] value;
/** The identifier of the encoding used to encode the bytes in {@code value}. */
private final byte coder;
static final boolean COMPACT_STRINGS;
static {
COMPACT_STRINGS = true;
}
/** Cache the hash code for the string */
private int hash; // Default to 0
}
不可变的String
String类是final的,存储的byte[]也是final的,所以保证String不可变。
不可变的好处
- 可以缓存hash值
- String Pool 的需要
- 帮助其他Objects的使用
- 例如Set<String>中,如果String可变,改变后的String可能违反set规则
- 安全性
- 例如在作为网络连接参数时,保证String不可变更具安全性
- 线程安全
构造函数
在将一个字符串对象作为另一个字符串对象的构造函数参数时,并不会完全复制 value 数组内容,而是都会指向同一个 value 数组
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
2. StringBuilder和StringBuffer
和String一样用byte[]存储,也有coder成员。但是这两个都是可变的,类内部提供append()之类的修改字符串的方法。
二者都继承自AbstractStringBuilder,其实相差不大,主要是StringBuffer中很多方法都被关键字synchronized
修饰,因此StringBuffer是线程安全的,而StringBuilder是线程不安全的。也因此,但单线程的情况下, StringBuilder的性能要比StringBuffer更好。
如果要对一个字符串做频繁修改,最好用StringBuilder,如果是在多线程的情况下(变量可能被多个线程访问),最好用StringBuffer。
3. StringPool 字符串常量池
String Pool保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定。可以使用 String 的 intern() 方法在运行过程中将字符串添加到 String Pool 中。
intern()
当一个字符串调用 intern() 方法时,如果 String Pool 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Pool 中字符串的引用;否则,就会在 String Pool 中添加一个新的字符串,并返回这个新字符串的引用。
String s1 = "hello"; //用字面量创建字符串,会自动将字符串放入 String Pool 中
String s2 = s1.intern(); //返回的是常量池中"Hello"字符串的引用
String Pool是一个固定大小的Hashtable,默认值大小长度是1009,如果放进String Pool的String非常多,就会造成Hash冲突严重,从而导致链表会很长,而链表长了后直接会造成的影响就是当调用 String.intern() 时性能会大幅下降。在jdk7中,StringTable的长度可以通过一个参数指定:XX:StringTableSize=99991
网友评论