我个人觉得理解String和StringBuffer以及StringBuilder的区别比较重要.在讨论他们的区别时,我们首先应该知道java中的String.
首先讨论String.
翻看String.java源码,会知道string的一个重要秘密:
在string中,其实内部是通过一个char数组来维护这个string的,并且还定义了一个记录该string在这个数组的起始位置的索引,以及定义了这个string的长度. 重点是他们都是final类型.
private final char[] value; private final int offset; private final int count;我们知道final修饰的变量是不可更改的.所以很快不得不接受一个现实:java中每一个string其实都是不可以更改的. 所以如果需要对一个string内的字符进行更改/移动等操作很显然是不可的. 这个时候会很快发现string中的方法replace()不是就可以更改一个string吗?为了消除这个问号,我们就来看看replace其中一个源码:
public String replace(char oldChar, char newChar) { char[] buffer = value; int _offset = offset; int _count = count; int idx = _offset; int last = _offset + _count; boolean copied = false; while (idx < last) { if (buffer[idx] == oldChar) { if (!copied) { char[] newBuffer = new char[_count]; System.arraycopy(buffer, _offset, newBuffer, 0, _count); buffer = newBuffer; idx -= _offset; last -= _offset; copied = true; } buffer[idx] = newChar; } idx++; } return copied ? new String(0, count, buffer) : this; }这个方法目的就是用newChar替换string中的所有的oldChar. 从上面的代码可以清楚的知道:当替换成功时候返回的其实是一个新的string,也就是说并不是原来的那个string对象.
还包括substring在内的所以其他方法,貌似是在改这个string,其实都不是,最后都是new了一个新的string.
这样一来问题就来了:往往实际开发中,对一个string反复修改是再正常不过的事情了,而且有时候我们还会高频率的这么做,如果每次操作都是new一个新的string,显然是不可的.在这种情况下StringBuffer和StringBuilder就出现了!目的就是为了解决这一问题.
查看StringBuffer和StringBuilder的源码会很快发现:其实他们几乎都一样,唯一的区别就是StringBuffer的几乎所有方法都采用了synchronized来同步,所以StringBuffer和StringBuilder区别就是线程安全问题.
所以接下来讨论的焦点就是StringBuffer如何实现对字符串的修改的.
StringBuffer和StringBuilder都是实现了虚类:AbstractStringBuilder,其中关键功能的实现都在这个虚类中,在AbstractStringBuilder中用一个char数组来维护这个字符串的,并且也定义了字符串的长度,如下代码所示:
private char[] value; private int count;这个和string里面定义的final char[] value不一样. 这里看看append()其中一个方法的实现:
final void append0(String string) { if (string == null) { appendNull(); return; } int length = string.length(); int newCount = count + length; if (newCount > value.length) { enlargeBuffer(newCount); } string._getChars(0, length, value, count); count = newCount; }上面的方法就是给StringBuffer或者StringBuilder后面追加一个string: 首先是确定当前的字符串数组长度是否不够,如果不够就扩容,然后将需要追加的string通过方法拷贝到value中.
从中可以发现,由于StringBuffer里面的字符数组value不是final,所以可以对其更改.而不需要像String那样new一个新的String对象.
java中String和StringBuffer以及StringBuilder的区别
原文:http://blog.csdn.net/green_shing/article/details/45071073