Java中, AbstractStringBuilder是 StringBuilder 和 StringBuffer 的父類. 因此瞭解StringBuilder和StringBuffer前, 有必要先了解一下這個抽象父類.html
這裏附上另外兩篇文章的鏈接:java
StringBuilder : http://www.cnblogs.com/noKing/p/jdk8_StringBuilder.html數組
StringBuffer : http://www.cnblogs.com/noKing/p/9431618.html app
在這裏存儲字符串內容源碼分析
在構造器內當即建立一個capacity大小的數組, 做爲value字段的值.ui
每次插入類的操做都會確保空間大小足夠. 若是不夠就會擴容, 再插入.spa
擴容是靠調用這個方法, 來確保每次有足夠的空間.3d
也就是說擴容後具體是多大, 還要根據newCapacity這個方法來定:指針
能夠看到, 擴容策略是原先的數組長度乘以2, 而後加2. htm
若是oldLength*2+2 以後的大小足夠大了, 那麼下次的數組大小就是這個數值了.
可是oldLength*2+2以後的大小仍是不夠, 那麼就直接採用傳進來的數據做爲目標大小.(先不討論hugeCapacity)
trimToSize的使用結果以下:
public class AbstractStringBuilderTest { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append("hello"); System.out.println("size:" + sb.length()); // 5 System.out.println("capacity" + sb.capacity()); // 16 sb.trimToSize(); System.out.println("size:" + sb.length()); // 5 System.out.println("capacity" + sb.capacity()); // 5 } }
詳細注意事項用下面的例子來講明:
public class AbstractStringBuilderTest { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append("hello"); System.out.println(sb.toString()); // hello System.out.println("size:" + sb.length()); // 5 System.out.println("capacity" + sb.capacity()); // 16 sb.setLength(2); System.out.println(sb.toString()); // he System.out.println("size:" + sb.length()); // 2 System.out.println("capacity" + sb.capacity()); // 16 sb.setLength(20); System.out.println(sb.toString()); // he\0\0\0\00\0\0\00\0\0\00\0\0\0\0\0 System.out.println("size:" + sb.length()); // 20 System.out.println("capacity" + sb.capacity()); // 34 sb.setLength(77); System.out.println("size:" + sb.length()); // 77 System.out.println("capacity" + sb.capacity()); // 77 } }
在上面這個demo中, 我用到了三次setLength. 可是每次調用後的結果都多多少少有些區別.
第1次調用: 由於setLength的參數比當前字符串的長度要小, 因此字符串被截短了, 長度也直接變爲了相應的數值.
第2次調用: 由於setLength的參數比當前字符串的長度要大, 因此多餘出來的部分用'\0'來補充.length是20. 而數組進行一次擴容就能夠hold住20這個大小, 因此就進行一次正常的擴容就好了. 正常的擴容就是原來的長度乘以2, 而後再加2, 因此是34.
第三次調用: 當前數組的長度是34, 而我setLength的參數是77. 34進行一次擴容才只是34*2+2 = 70. 由於77大於這個70, 因此capacity也就是77了.
一樣是參數大於當前數組的大小, 一樣是用'\0'來補充. 可是若是這個參數太大, 以致於一次擴容沒法hold住這個大小, 那麼capacity就會直接設置爲那個數值.
這段邏輯在newCapacity方法中. 代碼前面將擴容的時候粘貼過了.
咱們能夠看到charAt就是判斷數組越界, 來拋出異常.
返回值直接就是用的數組的下角標.
根據這個, setCharAt方法就不用多說了, 也是判斷是否越界, 而後給數組的相應位置賦值.
append方法的不少重載就是靠調用getChars方法來達到尾插的目的的. 很簡單, 就不提了.
就是appendNull方法, 很想吐槽...看完了眼前一亮....
嗯...還有append方法的bool型重載:
.....
能夠看到substring底層是直接調用的new String
兩個指針j和k. 關於中心對稱. 從中間開始一邊向兩邊遍歷, 一邊交換. 就完成了翻轉.
這個類沒什麼特別的, 但仍是稍微總結一下
1. 構造器裏當即初始化數組
2. 擴容方式爲 擴容前長度 * 2 + 2
3. 當前第2條說的不嚴謹. 首先想一想爲何擴容呢? 由於插入一個字符串的時候, 剩餘空間不足了, 因此擴容. 若是插入的這個字符串太長, 致使擴容一次也沒法容納下呢? 那麼就直接把長度設置爲 擴容前長度+ 插入的字符串長度 .
4. 大規模使用了System.arraycopy方法.