读 Character 原代码

今天粗略读了一下Character的代码,总结如下:

 

1. 定义了一些 UnicodeSubset (UnicodeBlock) , 每一个UnicodeBlock 代表一个代码段(范围),一部分代码段表示一个UnicodeScript, 任何一个CodePoint都属于某一个UnicodeScript,但不一定属于某一个UnicodeBlock(因为有些代码段不属于任何subset or block--block的name 为null ,这种情况下UnicodeScript就是"UNASSIGNED")

 

2. 不是很理解为什么  public static UnicodeScript of(int codePoint) 用了  Arrays.binarySearch 而 public static UnicodeBlock of(int codePoint) 却是自己写的二分算法。

 

   UnicodeScript的算法:

 int index = Arrays.binarySearch(scriptStarts, codePoint);
            if (index < 0)
                index = -index - 2;
            return scripts[index];

 

  UnicodeBlock的算法:

  int top, bottom, current;
            bottom = 0;
            top = blockStarts.length;
            current = top/2;

            // invariant: top > current >= bottom && codePoint >= unicodeBlockStarts[bottom]
            while (top - bottom > 1) {
                if (codePoint >= blockStarts[current]) {
                    bottom = current;
                } else {
                    top = current;
                }
                current = (top + bottom) / 2;
            }
            return blocks[current];
 

3. 为 0-127 (BASIC_LATIN , LATIN_1_SUPPLEMENT, LATIN_EXTENDED_A) 的Code Point建了cache pool, 这个范围的Character new出来都是单例。

 

4. isValidCodePoint 用了一个简易的小tricky 优化了一下:

 // Optimized form of:
        //     codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT
        int plane = codePoint >>> 16;
        return plane < ((MAX_CODE_POINT + 1) >>> 16);

 

5.  public static int charCount(int codePoint)  没有validate codePoint, 如果codePoint为负数时,也返回1就不太对了。

 

6.  isJavaIdentifierStart 和 isJavaIdentifierPart 可以用来判断一个字符可不可以用来作为Java标识符的开头和部分。

 

7.  字母 A-Z 可以用来表示基数为10 以上的进制中的一位digit。forDigit方法用来获得某个进制中某字母代表的digit,而digit方法可以得到某个进制中某个digit用哪个字母表示。

 

8.  unicode 为字符定义了一个数值,比如‘A’是10 , ‘Ⅸ’  是9, 可以用 getNumericValue方法得到一个Code Point的该值。

 

9.  isWiteSpace方法用来判断某个Code Point是不是Java认为的空白字符。

 

10.  isMirrored用来判断字符是否具有镜面对称的字符。比如'(' , '['.

 

11.  提供了一个 非public 的static char[] toUpperCaseCharArray(int codePoint) 是因为unicode 规定在 BMP中的unicode可能出现其大写是双字符的情况。比如 ß 的大写是 SS。这个方法会被String使用,所以只有String的toUpperCase会将ß 变成SS,而Character不行。

 

12. getName用来得到Code Point的名称,比如Character.getName(' ') 就是 SPACE, 对于没有名称的character就用它的UnicodeBlock名(下划线用空格替换)加上Code Point代码。比如 Character.getName('\uD801') 就是 HIGH SURROGATES D801。如果没有UnicodeBlock,就返回null。

 

13.  最后写了一点Test Case :

@Test
	public void testCharacter() {

		
        
		assertFalse(Character.isLetter('9'));
		
		assertFalse(Character.isAlphabetic('\t'));
		
		assertTrue(Character.isAlphabetic('Ⅸ'));
		
		assertFalse(Character.isJavaIdentifierStart('2'));
		
		assertFalse(Character.isJavaIdentifierPart(' '));
		
		assertFalse(Character.isUpperCase(Character.toUpperCase(0)));
		
        assertEquals(15, Character.getNumericValue('F'));
        
        assertEquals(9 , Character.getNumericValue('Ⅸ'));
        
        assertEquals(-1 , Character.digit('E' , 14));
        
        assertEquals(14, Character.digit('E' , 16));
        
        //maximal radix is 36 , because we only have 26 alphabet
        assertEquals( 0 , Character.forDigit(11, 37));
        
        assertEquals('b' , Character.forDigit(11, 35));
        
        assertFalse(Character.isMirrored(','));
        
        assertTrue(Character.isMirrored('('));
        
        assertEquals('\u00df', Character.toUpperCase('\u00df'));
        
        assertEquals( "SS" ,"\u00df".toUpperCase());
        
        assertEquals("SPACE", Character.getName(' '));
        
        assertEquals("HIGH SURROGATES D801", Character.getName('\uD801'));
        
        assertNull(Character.getName(0x102E0));
	}
 

 

 

你可能感兴趣的:(java,character)