string与stringbuild与stringbuffer

1 string源码

 

源码里可以看到String被final修饰并继承了三个接口
它们的值在创建后无法更改.Stringbuffers支持可变字符串。
因为String对象是不可变的,所以它们可以共享

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** 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 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;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

 

public native String intern();

注:方法注释会有写到,意思就是调用方法时,
如果常量池有当前String的值,就返回这个值,没有就加进去,返回这个值的引用
        String str1="a";
        String str2="b";
        String str3="ab";
        String str4 = str1+str2;
        String str5=new String("ab");

        System.out.println(str5==str3);//堆内存比较字符串池
        //intern如果常量池有当前String的值,就返回这个值,没有就加进去,返回这个值的引用
        System.out.println(str5.intern()==str3);//引用的是同一个字符串池里的
        System.out.println(str5.intern()==str4);//变量相加给一个新值,所以str4引用的是个新的
        System.out.println(str4==str3);//变量相加给一个新值,所以str4引用的是个新的
        
        false
        true
        false
        false
重点: --两个字符串常量或者字面量相加,不会new新的字符串,其他相加则是新值,(如 String str5=str1+"b";)

 

2 stringbuild与stringbuffer

stringbuffer线程安全

String一旦赋值或实例化后就不可更改,如果赋予新值将会重新开辟内存地址进行存储。 而StringBuffer类使用append和insert等方法改变字符串值时只是在原有对象存储的内存地址上进行连续操作,减少了资源的开销。  

append原理

@Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }


public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();  //如果str为null扩容原有长度+4,count记录null字数 
        int len = str.length();  //此时新的字符进来
        ensureCapacityInternal(count + len);//之前null字符长度+len 扩容
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }


count记录null字数
private AbstractStringBuilder appendNull() {
        int c = count;
        ensureCapacityInternal(c + 4);
        final char[] value = this.value;
        value[c++] = 'n';
        value[c++] = 'u';
        value[c++] = 'l';
        value[c++] = 'l';
        count = c;
        return this;
    }


   @Override
    public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
                                      int dstBegin)
    {
        super.getChars(srcBegin, srcEnd, dst, dstBegin);
    }


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

}

  //在原有数组的基础上进行复制数组
  public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
    {
        if (srcBegin < 0)
            throw new StringIndexOutOfBoundsException(srcBegin);
        if ((srcEnd < 0) || (srcEnd > count))
            throw new StringIndexOutOfBoundsException(srcEnd);
        if (srcBegin > srcEnd)
            throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);

       此时的value是全局变量  char[] value; copy之后更新stringbuffer当前值
    }

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值