String、StringBuilder、StringBuffer的区别

本文介绍有关String、StringBuilder、StringBuffer的区别。

String:

    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    /** 有参构造方法 */
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

在String类中,当我们创建String对象时,会将参数的value与hash属性进行传递,如当我们创建了如下的字符串对象时,

String a = new String("12345");

会将"12345"中的value与hash赋值给当前String对象(this代表当前对象)的char类型数组与int类型hash值(hash默认为0)。

因为数组value被final修饰,所以一旦String创建,不能改变。

另外字符串创建方式不同,创建的对象个数也不相同。

1.如果以new String("123456")这种方式创建对象则会创建两个对象,一个在堆内存中,一个在方法区的字符串常量池中;

2.如果以String s = "123456"这种方式声明,则只会在方法区常量池中创建一个对象。

 

StringBuilder:

StringBuilder继承了抽象类AbstractStringBuilder,当创建StringBuilder对象时,StringBuilder调用了父类中的构造方法,参数默认是16。父类构造方法则创建一个char类型数组,大小为16。

/** StringBuilder的无参构造方法,调用了AbstractStringBuilder的构造方法,参数默认是16 */ 
public StringBuilder() {
        super(16);
    }

/** AbstractStringBuilder的构造方法,创建一个char类型数组 */
AbstractStringBuilder(int capacity) {
        value = new char[capacity];
}

且这个char数组没有被final修饰,所以可变,我们可以使用append方法进行字符串的追加,StringBuilder中的append方法也是继承了父类中的append方法,StringBuilder默认容量是16,超过容量时会自动扩容,扩容为原容量的2倍+2。

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * The value is used for character storage.
     */
    char[] value;

    /**
     * The count is the number of characters used.
     */
    int count;

    /** AbstractStringBuilder中的append方法 */
    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        /** 此处要保证AbstractStringBuilder的容量,必要时会进行扩容操作,扩容时调用方法        
          * ensureCapacityInternal(int minimumCapacity),其中minimumCapacity为原长度与新追加    
          * 的字符串长度之和,即minimumCapacity = count + len。 
         */
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

    /** 扩容的方法,当传入的参数(新的容量大小)大于原来的容量时,进行扩容,调用        
      * expandCapacity(int minimumCapacity)。
      */
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0)
            expandCapacity(minimumCapacity);
    }

    /** 扩容后的容量为原容量的的2倍+2,并进行数组的拷贝。 */
    void expandCapacity(int minimumCapacity) {
        int newCapacity = value.length * 2 + 2;
        if (newCapacity - minimumCapacity < 0)
            newCapacity = minimumCapacity;
        if (newCapacity < 0) {
            if (minimumCapacity < 0) // overflow
                throw new OutOfMemoryError();
            newCapacity = Integer.MAX_VALUE;
        }
        value = Arrays.copyOf(value, newCapacity);
    }

    /** 在要输出StringBuilder中的字符串时使用该方法,该方法继承自Object,根据StringBuilder中的    
      * value与count创建了一个新的字符串对象并返回
      */
    public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }
}

StringBuffer:

StringBuffer与StringBuilder类似,最大的区别是,StringBuffer是线程安全的,因为使用了同步机制(synchronized对象锁),StringBuilder不是线程安全的。

/** StringBuffer继承了AbstractStringBuilder */
public final class StringBuffer 
extends AbstractStringBuilder 
implements java.io.Serializable, CharSequence
{

    /**
     * 声明一个字符串缓冲区,在调用toString方法时会使用到
     */
    private transient char[] toStringCache;

    /** StringBuffer的构造方法与StringBuilder相同 */
    public StringBuffer() {
        super(16);
    }

    /** StringBuffer的append方法与StringBuilder基本相同,但是使用了synchronized关键字,加上了    
      * 对象锁,保证了线程安全。 
      */
    public synchronized StringBuffer append(StringBuffer sb) {
        toStringCache = null;
        super.append(sb);
        return this;
    }
    
    /** 在输出StringBuffer时使用该方法,将StringBuffer中的字符串拷贝到字符串缓冲区    
      * toStringCache,并根据toStringCache创建String对象并返回。
      */
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }
}

总结:

String是一种引用数据类型,一旦创建不可改变。

StringBuilder相当于是一个字符串缓冲区,使用append方法进行字符串的追加,还有其他方法可对字符串进行操作,也就是说字符串可变,但不是线程安全的,可自动扩容,扩容后容量为原容量的2倍+2。

StringBuffer与StringBuilder基本上是相同的,但是StringBuffer是线程安全的,因为使用了同步机制(toString与append方法),有一个字符串缓冲区toStringCache(char类型数组),可自动扩容,扩容大小与StringBuilder相同。

StringBuilder与StringBuffer在使用时可先预估存储字符的容量,采用初始化容量的方式创建,可以省略扩容过程(底层数组的拷贝)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值