浅谈Java中的StringStringBufferStringBuilder
Posted 六欲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈Java中的StringStringBufferStringBuilder相关的知识,希望对你有一定的参考价值。
看再多别人的博客都不如自己翻一下源码:
String 内部使用final 修饰的byte[] 数组保存字符串,所以说String是不可变的。
@Stable private final byte[] value;
为什么说String相加每次都会返回新的String对象?看下源码就知道了
字符串相加的时候先调用concat方法,最终是调用System.arraycopy这个方法把两个byte[]数组相加,在new 一个新的String对象返回,所以说每次字符串相加都会返回新的String对象。我们特别注意一下这个getBytes方法和System.arraycopy这两个方法,接下来查看StringBuffer和StringBuilder对象的时候还会说到。
1 void getBytes(byte dst[], int dstBegin, byte coder) { 2 if (coder() == coder) { 3 System.arraycopy(value, 0, dst, dstBegin << coder, value.length); 4 } else { // this.coder == LATIN && coder == UTF16 5 StringLatin1.inflate(value, 0, dst, dstBegin, value.length); 6 } 7 }
1 public String concat(String str) { 2 int olen = str.length(); 3 if (olen == 0) { 4 return this; 5 } 6 if (coder() == str.coder()) { 7 byte[] val = this.value; 8 byte[] oval = str.value; 9 int len = val.length + oval.length; 10 byte[] buf = Arrays.copyOf(val, len); 11 System.arraycopy(oval, 0, buf, val.length, oval.length); 12 return new String(buf, coder); 13 } 14 int len = length(); 15 byte[] buf = StringUTF16.newBytesFor(len + olen); 16 getBytes(buf, 0, UTF16); 17 str.getBytes(buf, len, UTF16); 18 return new String(buf, UTF16); 19 }
StringBuffer:继承之AbstractStringBuilder这个抽象类,这个抽象类内部使用 byte[] value;保存字符串的值,我们注意下和String的区别,String内部的byte[]数组使用了final关键字修饰。
我们再看看下append这个方法,注意看下7行、16行、21行的代码 ,是不是和String 字符相加的方法很像?确实是的,也是通过System.arraycopy这个方法完成字符串的拼接,只不过append这个方法内部调用了ensureCapacityInternal这个方法完成了byte[]数组长度的判断和数组的扩容。
1 public AbstractStringBuilder append(String str) { 2 if (str == null) { 3 return appendNull(); 4 } 5 int len = str.length(); 6 ensureCapacityInternal(count + len); 7 putStringAt(count, str); 8 count += len; 9 return this; 10 } 11 12 private final void putStringAt(int index, String str) { 13 if (getCoder() != str.coder()) { 14 inflate(); 15 } 16 str.getBytes(value, index, coder); 17 } 18 19 void getBytes(byte dst[], int dstBegin, byte coder) { 20 if (coder() == coder) { 21 System.arraycopy(value, 0, dst, dstBegin << coder, value.length); 22 } else { // this.coder == LATIN && coder == UTF16 23 StringLatin1.inflate(value, 0, dst, dstBegin, value.length); 24 } 25 }
private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code int oldCapacity = value.length >> coder; if (minimumCapacity - oldCapacity > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity) << coder); } }
StringBuilder 和StringBuffer都是继承之AbstractStringBuilder这个抽象类他们区别就在以自身的方法,看下面的代码
StringBuffer调用父类方法的时候使用了synchronized这个关键字来修饰,StringBuilder 直接调用父类的方法。如果我们仔细查看源代码就会发现StringBuffer的方法都使用了
synchronized这个关键字来修饰,所以StringBuffer是线程安全的,StringBuilder是线程不安全的。
StringBuffer比StringBuffer效率较低的原因也是因为synchronized保证了线程安全。数据完整性和效率之间本身就有矛盾,不能两者兼得。
1 StringBuffer 的append方法 2 @Override 3 @HotSpotIntrinsicCandidate 4 public synchronized StringBuffer append(String str) { 5 toStringCache = null; 6 super.append(str); 7 return this; 8 } 9 10 StringBuffer 的append方法 11 @Override 12 @HotSpotIntrinsicCandidate 13 public StringBuilder append(String str) { 14 super.append(str); 15 return this; 16 }
!-- p.p1>!-- p.p1>!-- p.p1>!-- p.p1>!-- p.p1>!-- p.p1>!-- p.p1>
以上是关于浅谈Java中的StringStringBufferStringBuilder的主要内容,如果未能解决你的问题,请参考以下文章