StringBuilder、StringBuffer源碼分析
StringBuilder源碼分析
類結構
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
StringBuilder使用final關鍵字修飾,和String同樣不能夠被繼承java
StringBuilder繼承AbstractStringBuilder並實現了Serializable和CharSequence,能夠被序列化數組
方法
StringBuilder 的方法可能是直接調用父類AbstractStringBuilder的方法,這裏找幾個典型的方法看一下安全
StringBuilder append(Object obj)方法重寫父類的方法,追加Object類型的元素
@Override public StringBuilder append(Object obj) { return append(String.valueOf(obj));//String.valueOf(obj)獲取對象轉換成的字符串 } public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); } @Override public StringBuilder append(String str) { super.append(str); return this; } public AbstractStringBuilder append(String str) { if (str == null) return appendNull();//若是爲null追加字符串「null」 int len = str.length(); ensureCapacityInternal(count + len); //拷貝字符串到數組 str.getChars(0, len, value, count); count += len; return this; }
StringBuilder delete(int start, int end)刪除指定起點下標到指定結束下標的字符
@Override public StringBuilder delete(int start, int end) { super.delete(start, end); return this; } public AbstractStringBuilder delete(int start, int end) { if (start < 0) throw new StringIndexOutOfBoundsException(start); if (end > count)//若是結束下標>當前保存char的最大下標,直接賦值爲最大下標 end = count; if (start > end) throw new StringIndexOutOfBoundsException(); int len = end - start; if (len > 0) { //把刪除尾下標後的元素拷貝到刪除起始下標後 System.arraycopy(value, start+len, value, start, count-end); count -= len; } return this; }
StringBuilder replace(int start, int end, String str)使用字符串替換指定範圍內的字符
@Override public StringBuilder replace(int start, int end, String str) { super.replace(start, end, str); return this; } public AbstractStringBuilder replace(int start, int end, String str) { if (start < 0) throw new StringIndexOutOfBoundsException(start); if (start > count) throw new StringIndexOutOfBoundsException("start > length()"); if (start > end) throw new StringIndexOutOfBoundsException("start > end"); if (end > count) end = count; int len = str.length(); //計算須要的容量 int newCount = count + len - (end - start); //擴容 ensureCapacityInternal(newCount); //刪除指定範圍的字符 System.arraycopy(value, end, value, start + len, count - end); //在刪除的起始位置插入字符串 str.getChars(value, start); count = newCount; return this; }
StringBuilder insert(int offset, Object obj)在指定位置插入對象
@Override public StringBuilder insert(int offset, Object obj) { super.insert(offset, obj); return this; } public AbstractStringBuilder insert(int offset, Object obj) { return insert(offset, String.valueOf(obj));//String.valueOf(obj)獲取對象轉換的字符串 } public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); } @Override public StringBuilder insert(int offset, String str) { super.insert(offset, str); return this; } public AbstractStringBuilder insert(int offset, String str) { if ((offset < 0) || (offset > length())) throw new StringIndexOutOfBoundsException(offset); if (str == null) str = "null"; int len = str.length(); //擴容 ensureCapacityInternal(count + len); //把要插入位置後必定數量的字符(插入字符串長度)串移動後移必定距離(插入字符串長度) System.arraycopy(value, offset, value, offset + len, count - offset); //插入要插入的字符串 str.getChars(value, offset); count += len; return this; }
能夠看到,StringBuilder的append、insert、replace、delete都是對父類的char數組進行的一些操做,並無產生新的對象app
String toString() 最精髓的一個方法
@Override public String toString() { //把進過一些列修改後的最終char數組生成String return new String(value, 0, count); }
這裏咱們看到在toString的時候,把char數組生成了String,這也是爲何StringBuilder比String效率高的緣由,String類沒作一點修改都會生成新的對象,那麼在頻繁拼串和截取字符串時,效率固然不如StringBuilderide
StringBuffer源碼分析
類結構
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence
StringBuffer的類結構和StringBuilder的同樣源碼分析
方法
StringBuffer和StringBuilder同樣,不少方法都是調用父類AbstractStringBuilder的方法,咱們看幾個最主要的方法ui
StringBuffer append(Object obj)向StringBuffer中追加對象,和StringBuilder的追加對象同樣的代碼
@Override public synchronized StringBuffer append(Object obj) { toStringCache = null; super.append(String.valueOf(obj)); return this; } 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; } 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); } System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); }
StringBuffer delete(int start, int end)刪除指定範圍內的字符,和StringBuilder中delete方法代碼同樣
@Override public synchronized StringBuffer delete(int start, int end) { toStringCache = null; super.delete(start, end); return this; } public AbstractStringBuilder delete(int start, int end) { if (start < 0) throw new StringIndexOutOfBoundsException(start); if (end > count) end = count; if (start > end) throw new StringIndexOutOfBoundsException(); int len = end - start; if (len > 0) { System.arraycopy(value, start+len, value, start, count-end); count -= len; } return this; }
StringBuffer replace(int start, int end, String str)方法使用字符串替換指定範圍內的字符,和StringBuilder的replace方法代碼同樣
@Override public synchronized StringBuffer replace(int start, int end, String str) { toStringCache = null; super.replace(start, end, str); return this; } public AbstractStringBuilder replace(int start, int end, String str) { if (start < 0) throw new StringIndexOutOfBoundsException(start); if (start > count) throw new StringIndexOutOfBoundsException("start > length()"); if (start > end) throw new StringIndexOutOfBoundsException("start > end"); if (end > count) end = count; int len = str.length(); int newCount = count + len - (end - start); ensureCapacityInternal(newCount); System.arraycopy(value, end, value, start + len, count - end); str.getChars(value, start); count = newCount; return this; }
StringBuffer insert(int offset, Object obj)在指定位置插入字符串,也是和StringBuilder的insert方法代碼同樣
@Override public synchronized StringBuffer insert(int offset, Object obj) { toStringCache = null; super.insert(offset, String.valueOf(obj)); return this; } public AbstractStringBuilder insert(int offset, String str) { if ((offset < 0) || (offset > length())) throw new StringIndexOutOfBoundsException(offset); if (str == null) str = "null"; int len = str.length(); ensureCapacityInternal(count + len); System.arraycopy(value, offset, value, offset + len, count - offset); str.getChars(value, offset); count += len; return this; }
經過分析這幾個方法源碼,咱們能夠看到,StringBuilder和StringBuffer在方法的實現上是一致的,惟一的區別是StringBuffer的全部方法都加了synchronized鎖,因此是線程安全的this
String toString()把StringBuffer轉換成字符串
@Override public synchronized String toString() { if (toStringCache == null) { toStringCache = Arrays.copyOfRange(value, 0, count); } return new String(toStringCache, true); }
StringBuffer與StringBuilder都是在修改的時候並無產生新的對象,只是在調用toString方法是才轉換爲字符串。spa
總結
- StringBuilder和StringBuffer的類結構是一致的,都是使用父類的char數組保存字符。
- StringBuffer的全部方法都加了synchronized鎖,因此是線程安全的,可是這也使得它的效率比StringBuilder低。
- StringBuilder和StringBuffer的基本思想是一致的,對StringBuilder、StringBuffer的任何修改都不會產生新對象,這也使得StringBuilder、StringBuffer在進行大量拼串截取時比String的效率高。