String、StringBuilder、StringBuffer

StringBuilder

StringBuilder的构造器,无论是默认的无参构造器,或是指定容量的,或是指定字符串的,最终都是继承自AbstractStringBuilder的构造方法。

 AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }

主要看一下append()方法

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

//再定位到AbstractStringBuilder的append方法
  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;
    }

   private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0)
            expandCapacity(minimumCapacity);
    }
    //扩容方法
    void expandCapacity(int minimumCapacity) {
        //2*len+2
        int newCapacity = value.length * 2 + 2;
        //如果2*len+2不够,则指定append后的长度为capacity
        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);
    }
//看下String的getChars方法
   public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        if (srcEnd > value.length) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        //这里调用的是JVM实现的数组拷贝
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }

toString

  public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }

StringBuffer

StringBuffer多了一个字段toStringCache ,它表示上一次使用toString返回的字符串值的缓存。 每当StringBuffer被修改时清除。

    /**
     * A cache of the last value returned by toString. Cleared
     * whenever the StringBuffer is modified.
     */
    private transient char[] toStringCache;

StringBuffer的构造器同样继承于AbstractStringBuilder的构造方法

看一下StringBuffer的append方法 

//注意这个方法是加了synchronized的  
public synchronized StringBuffer append(String str) {
        //修改时将toStringCache清空
        toStringCache = null;
        super.append(str);
        return this;
    }
//同样调用的是AbstractStringBuilder的append方法
   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;
    }
   @Override
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

String

看一下String的equals方法。由于StringBuilder和StringBuffer都没有重写equals方法,所以它们的equals方法之比较两个对象是否是同一个,不比较里面的具体值。

  public boolean equals(Object anObject) {
       //如果是同一个字符串对象,则为真
        if (this == anObject) {
            return true;
        }
       //如果不是同一个字符串对象,则比较字符串中的各个字符
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                //原字符串的字符数组
                char v1[] = value;
                //待比较字符串的字符数组
                char v2[] = anotherString.value;
                int i = 0;
                //从第一个字符开始比较,遇到不同的字符则返回false
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

 

String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
System.out.println(s1 == s2); //true
System.out.println(s1 == s3); //false
System.out.println(s1.equals(s3));//true

记住 == 比较的是地址  String的equals()不仅比较地址,也比较字符串中的内容。

综合,效率方面 StringBuilder>StringBuffer>String。原因是String是常量,不可变的,每次修改都需要创建新的String对象;而StringBuilder和StringBuffer都是变量。又由于StringBuffer加了synchronized锁,需要申请获取锁以及释放锁,所以比StringBuilder慢。

StringBuffer是线程安全的,StringBuilder不是。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值