深切哀悼
抗击新冠肺炎疫情斗争牺牲烈士和逝世同胞

一、引言

本文内容主要为转载内容。
主要记录关于String、StringBuilder、StringBuffer的深入理解。

二、总结

MO_or将结合JDK8源码去理解String、StringBuilder、StringBuffer各自的优劣与使用场景。

2.1 String

先看下String的部分源码。
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];
    private int hash; // Default to 0

     public String() {
        this.value = new char[0];
    }

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

    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }    
    
    ...
}
String类使用了final关键字,表示此类是不支持继承的,并且value也是不能修改的。再执行以下代码。
public static void main(String[] args) {

    String string1 = new String("1");
    String string3 = "1";
    String string4 = "1";

    System.out.println(string1 == string3);
    System.out.println(string1.equals(string3));
    System.out.println(string3 == string4);
    System.out.println(string3.equals(string4));

}
输出:
false
true
true
true
回忆MO_or关于Static的感悟中的内存图。当String直接通过使用字符串实例化时,多个实例化都指向的常量池中同一个对象。
但缺点是频繁的字符串拼接操作,会造成内存空间的浪费。
需要注意的是这种字符串的拼接操作,从JDK8 开始,会自动被编译成StringBuilder,但任然不建议让JDK去自动转。

2.2 StringBuilder

StringBuilder的部分源码。
public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{
        public StringBuilder() {
        super(16);
    }

        public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
    }

        public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
    
    ...
}

abstract class AbstractStringBuilder implements Appendable, CharSequence {
        char[] value;
        int count;
        AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }


        public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

    ...
}
可以看到StringBuilder的value是个char数组,(当然从JDK9开始,value从char数组变成了byte数组)。每次append时都是通过调用native的System.arraycopy实现的(在getChars中调用的)。

2.3 StringBuffer

StringBuffer的部分源码。
public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{
    private transient char[] toStringCache;
    public StringBuffer() {
        super(16);
    }
    public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    ...
}
和StringBuilder一样,都是用了char数组保存value,append也是调用了AbstractStringBuilder的append方法。区别只是在于char数组加了transient关键字,以及方法上加了synchronized方法。

2.4 使用场景

综上所述,String、StringBuilder、StringBuffer的使用场景如下:
当处理定长字符串时,建议用String;
当处理变长字符串时,并且是单线程环境时,建议用StringBuilder;
当处理变长字符串时,并且是多线程环境时,建议用StringBuffer。

三、参考

深入理解String, StringBuffer, StringBuilder的区别(基于JDK1.8)
MO_or关于static的感悟
哔哩哔哩


MO_or
25 声望75 粉丝

小菜鸟的成长地。