String对比StringBuilder、StringBuffer及其扩容机制

本文分析了Java中的StringBuffer和StringBuilder类,讨论了它们在线程安全、效率和容量机制上的差异,以及与String的关系,重点介绍了StringBuilder的动态扩展和容量调整过程。
摘要由CSDN通过智能技术生成

简介                  


  • StringBuffer是Java1.0的API,StringBuilder是Java1.5的API
  • StringBuffer和StringBuilder都是继承自AbstractStringBuilder
  • 针对线程而言,StringBuffer是线程安全的StringBuilder是线程不安全的
  • 针对效率而言,StringBuffer效率较低StringBuilder较为高效

String类特点

  1. String类是被final修饰的

  2. 内部原理是一个char类型的字符数组

  3. 由于被final所修饰,所以它是采用定长数组存储数据的

  4. 由于是被final修饰的不可变类,因此不能被继承

     private final char value[];

StringBuffer和StringBuilder的特点

  1. 都是被final修饰的类,不能被继承
  2. StringBuilder和StringBuffer都是动态字符序列,采用动态扩展算法(扩容、拷贝)来实现动态存储数据方式从而完成字符串的动态存储,因此它们是采用变长数组存储的
  3. 内部原理是一个char类型的字符数组
  4. StringBuilder和StringBuffer的内存对象是可变的,因此它们是一个可变字符序列
    public final class StringBuilder
        extends AbstractStringBuilder
        implements java.io.Serializable, CharSequence{
    
    }
    

String,StringBuffer和StringBuilder之间的联系

  • String 继承于CharSequence,因此String是CharSequence类型
  • StringBuilder和StringBuffer同样实现了CharSequence  接口
  • CharSequence是字符串,因此String,StringBuilder和StringBuffer本质上都是通过字符数组实现的 
  • CharSequence与String都能用于定义字符串,区别是CharSequence是可读可写字符串,而String是只读字符串

StringBuilder和StringBuffer的容量机制和扩容机制

StringBuilder和StringBuffer的容量机制和扩容机制相同,区别在于StringBuffer引入synchronized 关键字进行加锁操作,从而保证了线程安全,下文将展开详细叙述。

容量机制

初始容量的声明通过无参构造方法和有参构造方法两种方式进行声明

1、不声明长度,使用无参构造方法创建实例对象时,会调用父类的构造方法,默认长度为16

public StringBuilder() {
        super(16);//调用父类构造方法
    }

2、使用有参构造方法有三种方式

public StringBuilder(int capacity) {
        super(capacity);//调用父类构造方法
    }

public StringBuilder(String str) {
        super(str.length() + 16);//调用父类构造方法
        append(str);
    }

public StringBuilder(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }

StringBuilder(int capacity)

构造一个不带字符具有指定初始长度的字符串缓冲区

StringBuilder(String str)

构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。初始长度为当前字符长度+16

StringBuilder(CharSequence seq)

构造一个字符串缓冲区,它包含与指定的 CharSequence 相同的字符

综上,初始容量实际上就是创建了一个长度为16的字符数组。

StringBuilder继承了抽象类AbstractStringBuilder,其中有三个重要字段

 char[] value;//保存字符

 int count;//已有字符长度

 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//最大数组大小

value表示存储字符,count表示数组中已有内容的长度MAX_ARRAY_SIZE表示最大的分配容量,即2^{31}-8若分配长度超过最大容量将会报OutOfMemoryError的错误:请求的数组大小超过限制

StringBuilder的主要操作append,insert等都在value上进行,String则是每次操作new一个新String,因此StringBuilder和StringBuffer的效率要高于String

StringBuilder扩容方法如下所示

//如果传入的实际最小容量>0,调用容量检测方法并传入参数实际最小容量minimumCapacity
public void ensureCapacity(int minimumCapacity) {
        if (minimumCapacity > 0)
            ensureCapacityInternal(minimumCapacity);
    }


//如果传入的minimumCapacity比原来的value长度大,则调用newCapacity方法
private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        //返回新数组,如果长度超过原数组长度,保留数组默认值
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }


private int newCapacity(int minCapacity) {
        // overflow-conscious code
        //扩大长度为原来的两倍加2
        int newCapacity = (value.length << 1) + 2;
        //如果新容量小于实际最小容量,将实际最小容量赋值给新容量
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        //如果新容量小于等于0或最大容量小于新容量,创建新容量
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }


private int hugeCapacity(int minCapacity) {
        //如果最大容量小于实际最小容量,抛出异常
        if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
            throw new OutOfMemoryError();
        }
        //如果实际最小容量大于最大容量返回实际最小容量,否则返回最大容量
        return (minCapacity > MAX_ARRAY_SIZE)
            ? minCapacity : MAX_ARRAY_SIZE;
    }

StringBuffer的加锁操作

StringBuffer的各个方法都使用了synchronized关键字修饰进行加锁操作,下示为部分StringBuffer中的方法

 @Override
    public synchronized int length() {
        return count;
    }

 @Override
    public synchronized int capacity() {
        return value.length;
    }


 @Override
    public synchronized void ensureCapacity(int minimumCapacity) {
        super.ensureCapacity(minimumCapacity);
    }

synchronized关键字的作用是当一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞,从而增强了线程的安全性,不过与此同时也相应地降低了效率。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值