Java·String、StringBuilder、StringBuffer

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, 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不可变。
不可变的好处

  1. 可以缓存hash值
  2. String Pool 的需要
  3. 帮助其他Objects的使用
    • 例如Set中,如果String可变,改变后的String可能违反set规则
  4. 安全性
    • 例如在作为网络连接参数时,保证String不可变更具安全性
  5. 线程安全

Program Creek : Why String is immutable in Java?

构造函数

在将一个字符串对象作为另一个字符串对象的构造函数参数时,并不会完全复制 value 数组内容,而是都会指向同一个 value 数组

public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}

Java基础-String

2. StringBuilder和StringBuffer

和String一样用byte[]存储,也有coder成员。但是这两个都是可变的,类内部提供append()之类的修改字符串的方法。
二者都继承自AbstractStringBuilder,其实相差不大,主要是StringBuffer中很多方法都被关键字synchronized修饰,因此StringBuffer是线程安全的,而StringBuilder是线程不安全的。也因此,但单线程的情况下, StringBuilder的性能要比StringBuffer更好。
如果要对一个字符串做频繁修改,最好用StringBuilder,如果是在多线程的情况下(变量可能被多个线程访问),最好用StringBuffer。

Java 之 synchronized 详解
深入理解Java并发之synchronized实现原理

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

深入解析 String#intern

你可能感兴趣的:(Java·String、StringBuilder、StringBuffer)