java Character類原始碼分析
一、使用
構建Character物件:
1 public class CharTest { 2 public static void main(String[] args) { 3 Character c1 = new Character('A'); 4 Character c2 = Character.valueOf('a'); 5 System.out.println(c1); // A 6 System.out.println(c2); // a 7 } 8 }
建構函式原始碼:
1@Deprecated(since="9") 2 public Character(char value) { 3 this.value = value; 4 }
可見,建構函式的形式不建議使用了。
另一種方式 Character.valueOf(),其原始碼:
1 @HotSpotIntrinsicCandidate 2 public static Character valueOf(char c) { 3 if (c <= 127) { // must cache 4 returnCharacterCache.cache[(int)c]; 5 } 6 return new Character(c); 7 }
valueOf()方法使用了註解 @HotSpotIntrinsicCandidate,在jvm層面會有比較高效的實現。字元的十進位制值小於等於127的話,將返回CharacterCache.cache[(int)c],返回事先快取的內容。
CharacterCache是個內部類,初始化CharacterCache的時候會快取十進位制0-127這128個字元(Character物件)。
1 privatestatic class CharacterCache { 2 private CharacterCache(){} 3 4 static final Character cache[] = new Character[127 + 1]; 5 6 static { 7 for (int i = 0; i < cache.length; i++) 8 cache[i] = new Character((char)i); 9 } 10 }
二、其他方法:
1、public char charValue() 返回此 Character
物件的值。
原始碼:
1 @HotSpotIntrinsicCandidate 2 public char charValue() { 3 return value; 4 }
使用:
System.out.println(c1.charValue()); // A
2、public int hashCode() 返回此 Character
的雜湊碼。
原始碼:
1 @Override 2 public int hashCode() { 3 return Character.hashCode(value); 4 } 5 6 public static int hashCode(char value) { 7 // char 轉為 int 8 return (int)value; 9 }
使用:
System.out.println(c1.hashCode()); // 65
3、public String toString() 返回表示此 Character
值的 String
物件。結果是一個長度為 1 的字串,其唯一元件是此 Character
物件表示的基本 char
值。
原始碼:
1 public String toString() { 2 char buf[] = {value}; 3 return String.valueOf(buf); 4 }
使用:
System.out.println(c1.toString()); // A
4、public static String toString(char c) 返回一個表示指定 char
值的 String
物件。結果是長度為 1 的字串,僅由指定的 char
組成。
原始碼:
1 public static String toString(char c) { 2 return String.valueOf(c); 3 }
使用:
System.out.println(Character.toString('A')); // A
5、public static boolean isValidCodePoint(int codePoint)
確定指定的程式碼點是否為從 0x0000 到 0x10FFFF 範圍之內的有效 Unicode 程式碼點值。該方法等效於以下表達式:codePoint >= 0x0000 && codePoint <= 0x10FFFF
原始碼:
1 public static final int MIN_CODE_POINT = 0x000000; 2 public static final int MAX_CODE_POINT = 0X10FFFF; 3 public static boolean isValidCodePoint(int codePoint) { 4 // Optimized form of: 5 // codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT 6 int plane = codePoint >>> 16; 7 return plane < ((MAX_CODE_POINT + 1) >>> 16); 8 }
有效的Unicode程式碼點的範圍是['\U+0000','\U+10FFFF'],即[0x000000,0x10FFFF],即[0000000, 10000 11111111 11111111],即[0, 1114111]
(MAX_CODE_POINT + 1) >>> 16, 即 0b00000000 00010001 00000000 00000000 >>> 16,等於00000000 00010001
如果codePoint大於MAX_CODE_POINT,則 (codePoint>>>16) 大於00000000 00010000。故大於MAX_CODE_POINT的值是無效的Unicode程式碼點
如果codePoint小於0,即codePoint為十進位制負數,則
-1
原碼:10000000 00000000 00000000 00000001
反碼:11111111 11111111 11111111 11111110
補碼:11111111 11111111 11111111 11111111
-1 >>> 16 即 11111111 11111111 11111111 11111111 >>> 16,等於11111111 11111111
-2147483648(帶符號int型別最小值)
原碼:10000000 00000000 00000000 00000000
反碼:11111111 11111111 11111111 11111111
補碼:10000000 00000000 00000000 00000000
-2147483648 >>> 16 即 10000000 00000000 00000000 00000000 >>> 16,等於 10000000 00000000
因為>>>是無符號右移動,所以如果負數(int型別),其儲存值的為該負數的補碼,最高位(第16位)為符號位1,
無符號右移16位之後,得到高16位,大於00000000 00010001。故十進位制負數是無效的Unicode 程式碼點。
確定指定的程式碼點是否為從 0x0000 到 0x10FFFF 範圍之內的有效 Unicode 程式碼點值。該方法等效於以下表達式:codePoint >= 0x0000 && codePoint <= 0x10FFFF
使用:
System.out.println(Character.isValidCodePoint(79)); // true
System.out.println(Character.isValidCodePoint(-79)); // false
6、public static boolean isSupplementaryCodePoint(int codePoint) 確定指定字元(Unicode 程式碼點)是否在增補字元範圍內。該方法呼叫以下表達式:codePoint >= 0x10000 && codePoint <= 0x10FFFF
原始碼:
1 public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x010000; 2 public static final int MAX_CODE_POINT = 0X10FFFF; 3 public static boolean isSupplementaryCodePoint(int codePoint) { 4 return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT 5 && codePoint < MAX_CODE_POINT + 1; 6 }
Unicode增補字元範圍:0x010000至0x10FFFF
使用:
System.out.println(Character.isSupplementaryCodePoint(65536)); // true
System.out.println(Character.isSupplementaryCodePoint(65535)); // false
7、
public static boolean isHighSurrogate(char ch) 確定給出的char
值是否為一個高代理項程式碼單元(也稱為 前導代理項程式碼單元)。這類值並不表示它們本身的字元,而被用來表示 UTF-16 編碼中的 增補字元。
public static boolean isLowSurrogate(char ch) 確定給定 char
值是否一個低代理項程式碼單元(也稱為 尾部代理項程式碼單元)。這類值並不表示它們本身的字元,而被用來表示 UTF-16 編碼中的 增補字元。
原始碼:
public static final char MIN_HIGH_SURROGATE = '\uD800'; public static final char MAX_HIGH_SURROGATE = '\uDBFF'; public static boolean isHighSurrogate(char ch) { // Help VM constant-fold; MAX_HIGH_SURROGATE + 1 == MIN_LOW_SURROGATE return ch >= MIN_HIGH_SURROGATE && ch < (MAX_HIGH_SURROGATE + 1); } public static final char MIN_LOW_SURROGATE = '\uDC00'; public static final char MAX_LOW_SURROGATE = '\uDFFF'; public static boolean isLowSurrogate(char ch) { return ch >= MIN_LOW_SURROGATE && ch < (MAX_LOW_SURROGATE + 1); }
高代理項範圍['\uD800', '\uDBFF'];
低代理項範圍['\uDC00', '\uDFFF']。
8、public static boolean isSurrogatePair(char high, char low) 確定指定的 char
值對是否為有效的代理項對。該方法等效於以下表達式:
原始碼:
1 public static boolean isSurrogatePair(char high, char low) { 2 return isHighSurrogate(high) && isLowSurrogate(low); 3 }
9、
public static int charCount(int codePoint)
-
確定表示指定字元(Unicode 程式碼點)所需的
char
值的數量。如果指定字元等於或大於 0x10000,則該方法返回的值為 2。否則,該方法返回的值為 1。該方法沒有驗證指定的字元是否為一個有效的 Unicode 程式碼點。如有必要,呼叫者必須使用
isValidCodePoint
驗證字元值。原始碼:
public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x010000; public static int charCount(int codePoint) { return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT ? 2 : 1; }
只判斷是否大於0x010000。
10、public static int toCodePoint(char high,char low) 將指定的代理項對轉換為其增補程式碼點值。該方法沒有驗證指定的代理項對。如有必要,呼叫者必須使用 isSurrogatePair
驗證它。
原始碼:
public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x010000; public static final char MIN_LOW_SURROGATE = '\uDC00'; public static final char MAX_HIGH_SURROGATE = '\uDBFF'; public static int toCodePoint(char high, char low) { // Optimized form of: // return ((high - MIN_HIGH_SURROGATE) << 10) // + (low - MIN_LOW_SURROGATE) // + MIN_SUPPLEMENTARY_CODE_POINT; return ((high << 10) + low) + (MIN_SUPPLEMENTARY_CODE_POINT - (MIN_HIGH_SURROGATE << 10) - MIN_LOW_SURROGATE); }
優化細節:
(high - MIN_HIGH_SURROGATE) << 10 ==> (high << 10) - (MIN_HIGH_SURROGATE << 10)
待續......................