寫在前面
說說這幾天看原始碼的感受吧,其實 jdk
中的原始碼設計是最值得進階學習的地方。我們在對 api
較為熟悉之後,完全可以去嘗試閱讀一些 jdk
原始碼,開啟 jdk
原始碼後,如果你英文能力稍微過得去,那麼原始碼有相當詳細的註釋告訴你 api
的含義,具體用法。假設平時在寫程式碼的過程中突然忘記了某個 api
的用法,那麼有些新手沒讀過原始碼的可能順手就開啟百度或者谷歌,搜尋 api 怎麼用?哈哈哈,面向谷歌程式設計,這樣的狀態可能會讓你一年的經驗重複n
年, 如果是閱讀過原始碼,則直接進去看看原始碼英文註釋,回想一下原始碼的實現即可使用,而且看過原始碼後,裡面有些程式碼細節是可以在平時編碼的過程中直接借鑑的。
廢話有點多啦~~滴滴滴,上車了。。。
上一篇 String 原始碼淺析(一) 中已經對String
前半部分原始碼做了解析,這篇把剩下的方法粗略的總結下...
String 成員方法
-
判斷字串是否相等,該方法繼承自
Object
類的重寫實現,原則上也是比較字串中的字元是否相等。public boolean equals(Object anObject) { //判斷形參跟當前字串物件地址是否相等,即是否為同一個物件,如果相等,則返回true if (this == anObject) { return true; } //如果形參為String型別物件 if (anObject instanceof String) { //強轉為String型別物件 String anotherString = (String)anObject; //當前字串物件的字元陣列長度 int n = value.length; //如果當前字串物件的字元陣列長度等於形參字串字元陣列長度 if (n == anotherString.value.length) { //當前字串字元陣列 char v1[] = value; //形參字串字元陣列 char v2[] = anotherString.value; //遍歷索引起始位置0 int i = 0; //遍歷當前字串字元陣列,每個索引位置的字元與形參字串索引位置字元比較,如果不相等則返回false while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } //以上條件都不滿足,最後返回false return false; } 複製程式碼
-
傳入
CharSequence
介面形參,實際是與StringBuffer
,StringBuilder
比較是否相等,因為StringBuffer
,StringBuilder
都實現了CharSequence
介面public boolean contentEquals(CharSequence cs) { //判斷形參是否是AbstractStringBuilder抽象類,實則因當傳入的是其子類:StringBuffer, StringBuilder if (cs instanceof AbstractStringBuilder) { //如果形參是StringBuffer型別物件 if (cs instanceof StringBuffer) { //同步鎖,呼叫nonSyncContentEquals方法比較兩種是否相等 synchronized(cs) { return nonSyncContentEquals((AbstractStringBuilder)cs); } } else { //如果形參物件是StringBuilder,則呼叫nonSyncContentEquals方法比較兩種是否相等 return nonSyncContentEquals((AbstractStringBuilder)cs); } } // 如果形參是String物件,則直接呼叫equals方法返回 if (cs instanceof String) { return equals(cs); } // 如果是其他的CharSequence實現類,則遍歷,一個個字元進行比較,找到一個字元不相等則直接返回false char v1[] = value; int n = v1.length; if (n != cs.length()) { return false; } for (int i = 0; i < n; i++) { if (v1[i] != cs.charAt(i)) { return false; } } //以上程式碼都不成立,走到最後直接返回true return true; } 複製程式碼
-
私有方法,非同步方式(執行緒不安全)比較與 AbstractStringBuilder 是否相等,實則是與其子類:StringBuffer, StringBuilder 比較大小,
contentEquals(CharSequence cs)
方法中核心比較程式碼就是呼叫該方法。private boolean nonSyncContentEquals(AbstractStringBuilder sb) { //當前字串物件字元陣列 char v1[] = value; //獲取形參字元陣列 char v2[] = sb.getValue(); //當前字串物件字元陣列長度 int n = v1.length; //如果當前字串物件字元陣列長度不等於形參字元陣列長度,則直接返回false if (n != sb.length()) { return false; } //遍歷當前字串物件字元陣列,與形參字元陣列逐一比較字元,找到一個字元不相等,則直接返回false for (int i = 0; i < n; i++) { if (v1[i] != v2[i]) { return false; } } //以上條件都不成立,程式碼走到最後則直接返回true return true; } 複製程式碼
-
公有方法,比較與
StringBuffer
物件是否相等,內部實則直接呼叫的contentEquals(CharSequence cs)
方法,可以說該方法是StringBuffer
的特別版吧。public boolean contentEquals(StringBuffer sb) { return contentEquals((CharSequence)sb); } 複製程式碼
-
匹配兩個字串部分片段是否相等
public boolean regionMatches(int toffset, String other, int ooffset, int len) { //當前字串字元陣列 char ta[] = value; //當前字串開始比較的起始位置,即偏移量 int to = toffset; //待比較的字串字元陣列 char pa[] = other.value; //待比較的字串起始位置,即偏移量 int po = ooffset; //索引檢查 1.偏移量小於0 2. 偏移量大於總長度-待比較的長度 //以上兩種情況直接返回false if ((ooffset < 0) || (toffset < 0) || (toffset > (long)value.length - len) || (ooffset > (long)other.value.length - len)) { return false; } //遍歷,找出不相等的字元,則返回false while (len-- > 0) { if (ta[to++] != pa[po++]) { return false; } } //不出意外,最終則返回true return true; } 複製程式碼
-
匹配兩個字串部分片段是否相等,同時判斷是否忽略大小寫
public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) { //當前字串字元陣列 char ta[] = value; //當前字串開始比較的起始位置,即偏移量 int to = toffset; //待比較的字串字元陣列 char pa[] = other.value; //待比較的字串起始位置,即偏移量 int po = ooffset; //索引檢查 1.偏移量小於0 2. 偏移量大於總長度-待比較的長度 //以上兩種情況直接返回false if ((ooffset < 0) || (toffset < 0) || (toffset > (long)value.length - len) || (ooffset > (long)other.value.length - len)) { return false; } //遍歷檢查字元是否相等,相等則跳過 while (len-- > 0) { char c1 = ta[to++]; char c2 = pa[po++]; if (c1 == c2) { continue; } //如果字元不相等,且需要忽略大小寫比較 if (ignoreCase) { //字元轉換為大寫 char u1 = Character.toUpperCase(c1); char u2 = Character.toUpperCase(c2); //如果相等,則繼續跳過 if (u1 == u2) { continue; } //轉換為小寫進行比較,如果相等則繼續跳過 if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { continue; } } //否則發現不相等,則直接返回false return false; } //不出意外,最終返回true return true; } 複製程式碼
-
忽略大小寫比較字串大小
public boolean equalsIgnoreCase(String anotherString) { //一句三目運算直接搞定 //如果當前字串物件地址與形參字串相等,則返回true //否則判斷形參字串是否為空,形參字串長度是否與當前字串長度相等,直接呼叫regionMatches比較兩個字串所有字元是否相等,同時忽略大小寫比較 //以上全部為true則相等 return (this == anotherString) ? true : (anotherString != null) && (anotherString.value.length == value.length) && regionMatches(true, 0, anotherString, 0, value.length); } 複製程式碼
-
比較兩個字串是否相等,該方法實現自
Comparable
介面,返回 int 結果,等於0,則字串相等,小於0,則前者小於後者,大於0,則前者大於後者public int compareTo(String anotherString) { //當前字串字元陣列長度 int len1 = value.length; //待比較字串字元陣列長度 int len2 = anotherString.value.length; //獲取較小的長度 int lim = Math.min(len1, len2); //當前字串字元陣列 char v1[] = value; //待比較的字串字元陣列 char v2[] = anotherString.value; //索引位置0開始 int k = 0; //遍歷較小的字元陣列 while (k < lim) { char c1 = v1[k]; char c2 = v2[k]; //如果字元不相等 if (c1 != c2) { //返回字元之差 return c1 - c2; } k++; } //如果字元都相等,則返回長度之差 return len1 - len2; } 複製程式碼
-
使用預設比較器不區分大小寫比較兩個字串大小
//初始化預設的比較器 public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator(); //預設的比較器,不區分大小寫 private static class CaseInsensitiveComparator implements Comparator<String>, java.io.Serializable { // use serialVersionUID from JDK 1.2.2 for interoperability private static final long serialVersionUID = 8575799808933029326L; public int compare(String s1, String s2) { //第一個字串長度 int n1 = s1.length(); //第二個字串長度 int n2 = s2.length(); //取小 int min = Math.min(n1, n2); //遍歷較小的字串 for (int i = 0; i < min; i++) { //獲取指定索引字元 char c1 = s1.charAt(i); char c2 = s2.charAt(i); //如果字元不相等 if (c1 != c2) { //轉化為大寫 c1 = Character.toUpperCase(c1); c2 = Character.toUpperCase(c2); //轉化為大寫後比較,不相等 if (c1 != c2) { //轉化為小寫繼續比較 c1 = Character.toLowerCase(c1); c2 = Character.toLowerCase(c2); //轉化為小寫字元,不相等 if (c1 != c2) { //直接返回字元之差 return c1 - c2; } } } } //不出意外,最終返回長度之差 return n1 - n2; } /** Replaces the de-serialized object. */ private Object readResolve() { return CASE_INSENSITIVE_ORDER; } } //內部直接呼叫預設比較器的compare方法 public int compareToIgnoreCase(String str) { return CASE_INSENSITIVE_ORDER.compare(this, str); } 複製程式碼
-
從指定偏移量開始,判斷是否以指定字串開頭
public boolean startsWith(String prefix, int toffset) { //當前字串字元陣列 char ta[] = value; //偏移量 int to = toffset; //指定字串字首字元陣列 char pa[] = prefix.value; //索引位置0開始 int po = 0; //指定字串字首陣列長度 int pc = prefix.value.length; //偏移量小於0 或者 //偏移量大於總長度-字串字首長度,則直接返回false if ((toffset < 0) || (toffset > value.length - pc)) { return false; } //遍歷字首字串 while (--pc >= 0) { //從偏移量開始檢索,找到字元不相等,則返回false if (ta[to++] != pa[po++]) { return false; } } //不出意外,最後則返回true return true; } 複製程式碼
-
從字串開頭,判斷是否以指定字串開頭
public boolean startsWith(String prefix) { //直接呼叫startsWith過載方法,偏移量為0 return startsWith(prefix, 0); } 複製程式碼
-
判斷是否以指定字串結尾,內部直接呼叫的 startsWith 方法,偏移量為總字串長度-字尾字串長度即可。
public boolean endsWith(String suffix) { return startsWith(suffix, value.length - suffix.value.length); } 複製程式碼
-
從指定偏移量開始,搜尋指定字元在字串中第一次出現的索引位置
public int indexOf(int ch, int fromIndex) { //當前字串字元陣列長度 final int max = value.length; //如果偏移量小於0,則重置為0 if (fromIndex < 0) { fromIndex = 0; } else if (fromIndex >= max) { //偏移量大於總長度,則返回-1,意味著找不到指定字元 return -1; } if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { //當前字串字元陣列 final char[] value = this.value; //從偏移量位置開始遍歷 for (int i = fromIndex; i < max; i++) { //找到相等的字元,則返回索引 if (value[i] == ch) { return i; } } //找不到則返回-1 return -1; } else { return indexOfSupplementary(ch, fromIndex); } } 複製程式碼
-
查詢指定字元在字串中第一次出現的索引位置,從偏移量0開始遍歷查詢
public int indexOf(int ch) { return indexOf(ch, 0); } 複製程式碼
-
查詢指定字元在字串中最後一次出現的索引位置,從指定偏移量開始遍歷
public int lastIndexOf(int ch, int fromIndex) { if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { //當前字串字元陣列 final char[] value = this.value; //偏移量與字串最後的位置取小 int i = Math.min(fromIndex, value.length - 1); //從後遍歷字元陣列 for (; i >= 0; i--) { //找到相等的字元,返回索引 if (value[i] == ch) { return i; } } //找不到則返回-1 return -1; } else { return lastIndexOfSupplementary(ch, fromIndex); } } 複製程式碼
-
查詢指定字元在字串中最後一次出現的索引位置,從字串最後一個索引位置開始遍歷查詢
public int lastIndexOf(int ch) { return lastIndexOf(ch, value.length - 1); } 複製程式碼
-
從指定位置開始,查詢字串在源字串中第一次出現的的索引位置,內部實則直接呼叫的
indexOf
內部靜態方法public int indexOf(String str, int fromIndex) { return indexOf(value, 0, value.length, str.value, 0, str.value.length, fromIndex); } 複製程式碼
-
查詢字串在源字串中第一次出現的的索引位置,內部實則直接呼叫的上述
indexOf
方法,fromIndex
預設從0開始public int indexOf(String str) { return indexOf(str, 0); } 複製程式碼
-
從指定位置開始,查詢字串在源字串中最後一次出現的的索引位置,內部實則直接呼叫的
lastIndexOf
內部靜態方法public int lastIndexOf(String str, int fromIndex) { return lastIndexOf(value, 0, value.length, str.value, 0, str.value.length, fromIndex); } 複製程式碼
-
查詢字串在源字串中最後一次出現的的索引位置,內部實則直接呼叫的上述
lastIndexOf
方法,fromIndex
預設從value.length
開始public int lastIndexOf(String str) { return lastIndexOf(str, value.length); } 複製程式碼
-
按照指定區間裁剪字串,返回子字串,
beginIndex
起始位置(包含),endIndex
結束位置(不包含)public String substring(int beginIndex, int endIndex) { //起始位置小於0,丟擲索引越界異常 if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } //結束位置大於字串總長度,則丟擲索引越界異常 if (endIndex > value.length) { throw new StringIndexOutOfBoundsException(endIndex); } //待擷取的字串長度 int subLen = endIndex - beginIndex; //待擷取的字串長度小於0,則丟擲索引越界異常 if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } //三目判斷 起始位置等於0,並且結束位置等於字串長度,則表示為擷取總長度,返回當前字串物件 //否則重新new一個字串例項,從beginIndex開始,擷取subLen長度 return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen); } 複製程式碼
-
從起始位置
beginIndex
開始擷取源字串到結尾,返回子字串public String substring(int beginIndex) { //起始位置小於0,丟擲索引越界異常 if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } //待擷取的字串長度 int subLen = value.length - beginIndex; //待擷取的字串長度小於0,則丟擲索引越界異常 if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } //三目判斷 起始位置等於0,則表示為擷取總長度,返回當前字串物件,否則重新new一個新的字串例項,從beginIndex開始,擷取subLen長度 return (beginIndex == 0) ? this : new String(value, beginIndex, subLen); } 複製程式碼
-
按照指定區間裁剪字串,返回
CharSequence
介面,beginIndex
起始位置(包含),endIndex
結束位置(不包含),內部實則直接呼叫的substring
方法,只是返回的是最上層介面罷了public CharSequence subSequence(int beginIndex, int endIndex) { return this.substring(beginIndex, endIndex); } 複製程式碼
-
字串拼接,將目標字串拼接在尾部,返回新的字串
public String concat(String str) { //待拼接的字串長度 int otherLen = str.length(); //如果待拼接的字串長度等於0,則直接返回當前字串物件 if (otherLen == 0) { return this; } //當前字串長度 int len = value.length; //將當前字串字元陣列拷貝到新的字元陣列buf[]中,長度擴容至len + otherLen char buf[] = Arrays.copyOf(value, len + otherLen); //將待拼接的字元陣列拷貝至buf[]中,從len開始,理論上這部操作完之後,字元陣列已經拼接成功了 str.getChars(buf, len); //利用最新的字元陣列,重新new一個新的字串例項返回 return new String(buf, true); } 複製程式碼
-
將字串中指定字元
oldChar
替換為新的字元newChar
public String replace(char oldChar, char newChar) { //如果舊的字元跟新的字元不相等,才執行替換邏輯,否則直接返回當前字串物件 if (oldChar != newChar) { //當前字串長度 int len = value.length; //索引從-1開始 int i = -1; //當前字串字元陣列 char[] val = value; //遍歷當前字元陣列,從0開始,因為++i之後等於0 while (++i < len) { //找到與oldChar相等的字元,則中斷迴圈 if (val[i] == oldChar) { break; } } //如果oldChar索引位置i小於當前字元陣列長度,意味著在當前字串中找到了oldChar if (i < len) { //初始化字串長度的字元陣列 char buf[] = new char[len]; //從0開始遍歷到oldChar所在位置,將字元放入buf for (int j = 0; j < i; j++) { buf[j] = val[j]; } //從oldChar索引位置i開始遍歷到字串結尾 while (i < len) { //當前字元 char c = val[i]; //如果當前字元等於oldChar,則newChar賦值給buf[i],否則不變 buf[i] = (c == oldChar) ? newChar : c; i++; } //最後根據buf陣列重新new一個新的字串例項返回 return new String(buf, true); } } return this; } 複製程式碼
-
根據字串正則
regex
匹配字串,返回boolean,內部實則是呼叫正則匹配的api方法public boolean matches(String regex) { return Pattern.matches(regex, this); } 複製程式碼
-
判斷字串是否包含指定字元序列
CharSequence
,內部實則是呼叫indexOf
方法,判斷返回結果是否大於-1public boolean contains(CharSequence s) { return indexOf(s.toString()) > -1; } 複製程式碼
-
根據給定的新的子字串
replacement
,替換第一個匹配給定的正規表示式regex
的子字串,內部實則呼叫的是Matcher
類的replaceFirst
方法public String replaceFirst(String regex, String replacement) { return Pattern.compile(regex).matcher(this).replaceFirst(replacement); } 複製程式碼
-
根據給定的新的子字串
replacement
,替換所有匹配給定的正規表示式regex
的子字串,內部實則呼叫的是Matcher
類的replaceAll
方法public String replaceAll(String regex, String replacement) { return Pattern.compile(regex).matcher(this).replaceAll(replacement); } 複製程式碼
-
更加通用的字串替換方法,將匹配到的
target
字元序列全部替換為replacement
字元序列,內部呼叫的也是Matcher
類的replaceAll
方法public String replace(CharSequence target, CharSequence replacement) { return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( this).replaceAll(Matcher.quoteReplacement(replacement.toString())); } 複製程式碼
-
去除字串前後空格
public String trim() { //當前字串長度 int len = value.length; //索引標誌位 int st = 0; //當前字串字元陣列 char[] val = value; //從0開始遍歷迴圈,查詢到空格的字元,則索引往前+1 while ((st < len) && (val[st] <= ' ')) { st++; } //從字串尾部開始遍歷迴圈,查詢到空格字元,則長度往後-1 while ((st < len) && (val[len - 1] <= ' ')) { len--; } //如果st索引大於0或者長度len小於總長度,則返回裁剪字串st偏移量開始,裁剪len長度,否則直接返回當前字串物件 return ((st > 0) || (len < value.length)) ? substring(st, len) : this; } 複製程式碼
-
字串轉化
toString
,繼承自Object
重寫的方法,直接返回當前字串物件public String toString() { return this; } 複製程式碼
-
字串轉化為字元陣列
public char[] toCharArray() { //初始化字串長度的字元陣列 char result[] = new char[value.length]; //將字串本身的字元陣列拷貝至result[]並返回結果 System.arraycopy(value, 0, result, 0, value.length); return result; } 複製程式碼
String 靜態方法
-
不對外公開的內部靜態方法,從字串
source
指定索引fromIndex
開始遍歷,從偏移量sourceOffset
,在原始字串長度sourceCount
範圍內查詢目標字串target
中偏移量targetOffset
開始,長度為targetCount
的字串索引第一次出現的位置。static int indexOf(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex) { //如果起始位置大於等於源字串指定長度 if (fromIndex >= sourceCount) { //如果目標字串查詢的長度為0,則直接返回源字串長度,否則返回-1表示未找到 return (targetCount == 0 ? sourceCount : -1); } //起始位置小於0 if (fromIndex < 0) { //重置為0 fromIndex = 0; } //目標字串長度為0,代表為空字串”“ if (targetCount == 0) { //直接返回起始位置 return fromIndex; } //目標字串第一個字元 char first = target[targetOffset]; //從源字元偏移量開始,計算最大的遍歷次數 int max = sourceOffset + (sourceCount - targetCount); //遍歷 for (int i = sourceOffset + fromIndex; i <= max; i++) { //迴圈找出第一個字元 if (source[i] != first) { while (++i <= max && source[i] != first); } //todo 這段暫時沒看明白 by zhangshaolin if (i <= max) { int j = i + 1; int end = j + targetCount - 1; for (int k = targetOffset + 1; j < end && source[j] == target[k]; j++, k++); if (j == end) { /* Found whole string. */ return i - sourceOffset; } } } //最終沒找到 則返回-1 return -1; } 複製程式碼
-
不對外公開的靜態方法,上述方法的另一個過載形式,內部實則直接呼叫的上述方法,
targetCount
預設傳入target.value.length
static int indexOf(char[] source, int sourceOffset, int sourceCount, String target, int fromIndex) { return indexOf(source, sourceOffset, sourceCount, target.value, 0, target.value.length, fromIndex); } 複製程式碼
-
不對外公開的內部靜態方法,從字串
source
指定索引fromIndex
開始遍歷,從偏移量sourceOffset
,在原始字串長度sourceCount
範圍內查詢目標字串target
中偏移量targetOffset
開始,長度為targetCount
的字串索引第一次出現的位置。static int lastIndexOf(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex) { //源字元長度-目標字元長度,獲取起始位置 int rightIndex = sourceCount - targetCount; //起始位置小於0,直接返回-1表示未找到目標 if (fromIndex < 0) { return -1; } //如果形參起始位置大於計算的實際起始位置,則直接賦值給fromIndex if (fromIndex > rightIndex) { fromIndex = rightIndex; } //如果目標字串長度為0,表示為空字串,則直接返回起始位置 if (targetCount == 0) { return fromIndex; } //獲取目標字串最後一個索引位置 int strLastIndex = targetOffset + targetCount - 1; //獲取目標字串最後一個字元 char strLastChar = target[strLastIndex]; //獲取最小遍歷次數 int min = sourceOffset + targetCount - 1; //最小遍歷次數+起始位置 int i = min + fromIndex; //迴圈查詢最後一個字元 startSearchForLastChar: while (true) { while (i >= min && source[i] != strLastChar) { i--; } //如果i<min,則代表查詢不到最後一個字元 返回-1 if (i < min) { return -1; } //todo 這段邏輯暫時沒看明白 by zhangshaolin int j = i - 1; int start = j - (targetCount - 1); int k = strLastIndex - 1; while (j > start) { if (source[j--] != target[k--]) { i--; //找不到,繼續跳過外層迴圈 continue startSearchForLastChar; } } return start - sourceOffset + 1; } } 複製程式碼
-
不對外公開的靜態方法,上述方法的另一個過載形式,內部實則直接呼叫的上述方法,
targetCount
預設傳入target.value.length
static int lastIndexOf(char[] source, int sourceOffset, int sourceCount, String target, int fromIndex) { return lastIndexOf(source, sourceOffset, sourceCount, target.value, 0, target.value.length, fromIndex); } 複製程式碼
-
將任意
Object
物件轉化為字串物件返回,內部實則也是呼叫的Object
的toString
方法,返回結果取決於該方法的具體實現public static String valueOf(Object obj) { //如果obj為空,則返回"null",否則返回物件的toString返回的字串結果 return (obj == null) ? "null" : obj.toString(); } 複製程式碼
-
將字元陣列轉化為字串物件返回,內部實際是用字元陣列為引數 重新 new 了一個新的字串物件,並返回
public static String valueOf(char data[]) { return new String(data); } 複製程式碼
-
將字元陣列轉化為字串物件返回,同時指定索引偏移量
offset
,擷取的長度count
,內部實際是重新 new 了一個新的字串物件,並返回public static String valueOf(char data[], int offset, int count) { return new String(data, offset, count); } 複製程式碼
-
與上一個方法效果一致,只是方法名稱不同罷了
public static String copyValueOf(char data[], int offset, int count) { return new String(data, offset, count); } 複製程式碼
-
與
valueOf(char data[])
效果一致,只是方法名稱不同罷了public static String copyValueOf(char data[]) { return new String(data); } 複製程式碼
-
將
boolean
型別資料轉化為字串物件返回public static String valueOf(boolean b) { //為真 則返回"true" 否則返回"false" return b ? "true" : "false"; } 複製程式碼
-
將字元轉化為字串物件返回
public static String valueOf(char c) { //初始化字元陣列 char data[] = {c}; //重新new一個新的字串物件返回 return new String(data, true); } 複製程式碼
-
將int資料轉換為字串物件返回,內部實際是呼叫的
Integer.toString()
方法public static String valueOf(int i) { return Integer.toString(i); } 複製程式碼
-
將long資料轉換為字串物件返回,內部實際是呼叫的
Long.toString()
方法public static String valueOf(long l) { return Long.toString(l); } 複製程式碼
-
將float資料轉換為字串物件返回,內部實際是呼叫的
Float.toString()
方法public static String valueOf(float f) { return Float.toString(f); } 複製程式碼
-
將double資料轉換為字串物件返回,內部實際是呼叫的
Double.toString()
方法public static String valueOf(double d) { return Double.toString(d); } 複製程式碼
簡單總結
- 把
String
原始碼全部大致過了一遍之後,感慨jdk
程式碼設計的強大,幾天時間要完全看懂是不容易的,目前也還有很多地方沒有完全明白 - 原始碼並不可怕,可怕的是自己的畏懼心理,認為原始碼很難啃不動,其實不然,下定決心看下去,遇到不懂的可以先
pass
,後面再回頭看可能就豁然開朗了。 String
內部本質就是操作字元陣列value[]
- 因為本質就是操作字元陣列,內部用到了大量的
Arrays.copyOf
,以及System.arraycopy
方法
最後
看原始碼不易,如果文中有錯誤之處,還請留言指出,一起學習,一起進步,謝謝!
更多原創文章會第一時間推送公眾號【張少林同學】,歡迎關注!