String 部分源碼分析
阿新 • • 發佈:2018-11-18
def default 返回 match row 同時 ble subst 直接
String
- 無參數構造函數
/** * 底層存儲字符串的目標字節數組, * Jdk 8 之前都是字符數組 private final char[] value; */ @Stable private final byte[] value; /** * 編碼底層字節數組的字符集,支持 LATIN1、UTF16 */ private final byte coder; /** * 字符串的哈希碼值,默認為 0 */ private int hash; // Default to 0 /** * 創建一個空字符串 * created by ZXD at 18 Nov 2018 T 11:17:48 */ public String() { this.value = "".value; this.coder = "".coder; }
- 基於字節數組創建字符串
public String(byte[] bytes) { this(bytes, 0, bytes.length); } public String(byte bytes[], int offset, int length) { checkBoundsOffCount(offset, length, bytes.length); // 對目標字節數組進行編碼 StringCoding.Result ret = StringCoding.decode(bytes, offset, length); // 獲取編碼後的字節數組 this.value = ret.value; // 獲取編碼後的字符集 this.coder = ret.coder; } public String(byte bytes[], Charset charset) { this(bytes, 0, bytes.length, charset); } public String(byte bytes[], int offset, int length, Charset charset) { // 防禦式編程,null 校驗 if (charset == null) throw new NullPointerException("charset"); checkBoundsOffCount(offset, length, bytes.length); // 根據指定的字符集對字節數組進行編碼 StringCoding.Result ret = StringCoding.decode(charset, bytes, offset, length); this.value = ret.value; this.coder = ret.coder; } public String(byte bytes[], String charsetName) throws UnsupportedEncodingException { this(bytes, 0, bytes.length, charsetName); } public String(byte bytes[], int offset, int length, String charsetName) throws UnsupportedEncodingException { if (charsetName == null) throw new NullPointerException("charsetName"); checkBoundsOffCount(offset, length, bytes.length); // 根據指定的字符集對字節數組進行編碼,編碼名稱錯誤時,拋出 UnsupportedEncodingException 異常 StringCoding.Result ret = StringCoding.decode(charsetName, bytes, offset, length); this.value = ret.value; this.coder = ret.coder; }
- 基於字符數組創建字符串
public String(char value[]) { this(value, 0, value.length, null); } public String(char value[], int offset, int count) { this(value, offset, count, rangeCheck(value, offset, count)); } private static Void rangeCheck(char[] value, int offset, int count) { // 字符串下標合法性校驗 checkBoundsOffCount(offset, count, value.length); return null; } String(char[] value, int off, int len, Void sig) { // 特殊場景優化處理 if (len == 0) { this.value = "".value; this.coder = "".coder; return; } if (COMPACT_STRINGS) { // 如果啟用壓縮,則將字符數組壓縮,字符集設置為 LATIN1 byte[] val = StringUTF16.compress(value, off, len); if (val != null) { this.value = val; this.coder = LATIN1; return; } } // 字符數組不壓縮時,字符集設置為 UTF16 this.coder = UTF16; this.value = StringUTF16.toBytes(value, off, len); }
- 字符串內容相等性比較
public boolean equals(Object anObject) {
// 地址相等則直接返回 true
if (this == anObject) {
return true;
}
// 形參對象為字符串
if (anObject instanceof String) {
String aString = (String)anObject;
// 字符編碼相同時才能做比較
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}
- 字符串的長度
public int length() {
return value.length >> coder();
}
byte coder() {
return COMPACT_STRINGS ? coder : UTF16;
}
@Native static final byte LATIN1 = 0;
@Native static final byte UTF16 = 1; // Unicode字符集的抽象碼位映射為16位長的整數
- 比較字符串內容並且不區分大小寫
public boolean equalsIgnoreCase(String anotherString) {
return (this == anotherString) ? true
: (anotherString != null) // 形參字符串不為 null
&& (anotherString.length() == length()) // 兩個字符串長度一致
&& regionMatches(true, 0, anotherString, 0, length()); // 編碼後的區域是否匹配
}
- 字符串拼接
public String concat(String str) {
int olen = str.length();
if (olen == 0) {
return this;
}
// 字符集相同時,直接通過數組拷貝進行拼接
if (coder() == str.coder()) {
byte[] val = this.value;
byte[] oval = str.value;
int len = val.length + oval.length;
byte[] buf = Arrays.copyOf(val, len);
System.arraycopy(oval, 0, buf, val.length, oval.length);
return new String(buf, coder);
}
int len = length();
// 使用 UTF16 編碼計算目標字節數組長度,並將它們都拷貝進去。
byte[] buf = StringUTF16.newBytesFor(len + olen);
getBytes(buf, 0, UTF16);
str.getBytes(buf, len, UTF16);
return new String(buf, UTF16);
}
- 字符串截取
public String substring(int beginIndex, int endIndex) {
int length = length();
// 索引合法性檢測
checkBoundsBeginEnd(beginIndex, endIndex, length);
int subLen = endIndex - beginIndex;
// 特殊場景優化處理,截取的子字符串就是目標字符串
if (beginIndex == 0 && endIndex == length) {
return this;
}
return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
: StringUTF16.newString(value, beginIndex, subLen);
}
/**
* 起始索引和結束索引不在 0到 length()-1 範圍內,則拋出 IndexOutOfBoundsException 異常
* 結束索引大於起始索引,則拋出 IndexOutOfBoundsException 異常
*/
static void checkBoundsBeginEnd(int begin, int end, int length) {
if (begin < 0 || begin > end || end > length) {
throw new StringIndexOutOfBoundsException(
"begin " + begin + ", end " + end + ", length " + length);
}
}
- 獲取字符串中指定索引處的單個字符
public char charAt(int index) {
if (isLatin1()) {
return StringLatin1.charAt(value, index);
} else {
return StringUTF16.charAt(value, index);
}
}
StringLatin1#charAt
public static char charAt(byte[] value, int index) {
if (index < 0 || index >= value.length) {
throw new StringIndexOutOfBoundsException(index);
}
return (char)(value[index] & 0xff);
}
- 目標字符串是否包含子字符串
public boolean contains(CharSequence s) {
return indexOf(s.toString()) >= 0;
}
- 字符串是否為空
public boolean isEmpty() {
return value.length == 0;
}
- 字符串替換
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
String ret = isLatin1() ? StringLatin1.replace(value, oldChar, newChar)
: StringUTF16.replace(value, oldChar, newChar);
if (ret != null) {
return ret;
}
}
return this;
}
public String replace(CharSequence target, CharSequence replacement) {
// 需要查找的字符序列
String tgtStr = target.toString();
// 需要替換的字符序列
String replStr = replacement.toString();
// 如果要查找的字符序列沒有在目標字符串中,則返回其本身
int j = indexOf(tgtStr);
if (j < 0) {
return this;
}
// 查找字符序列的長度
int tgtLen = tgtStr.length();
int tgtLen1 = Math.max(tgtLen, 1);
// 當期字符串的長度
int thisLen = length();
int newLenHint = thisLen - tgtLen + replStr.length();
if (newLenHint < 0) {
throw new OutOfMemoryError();
}
StringBuilder sb = new StringBuilder(newLenHint);
int i = 0;
// 在 StringBuilder 指定的索引處追加字符串,並重新獲取要查找的子字符串索引進行循環替換。
do {
sb.append(this, i, j).append(replStr);
i = j + tgtLen;
} while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0);
return sb.append(this, i, thisLen).toString();
}
- 基於正則表達式替換字符串
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
- 基於正則表達式替換首次出現的字符串
public String replaceFirst(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
}
String 部分源碼分析