[十一]基礎數據類型之Character

Character與Unicode

Character 基本數據類型char  的包裝類
Character 類型的對象包含一個 char 類型的字段  
image_5bc67cf1_5cb3
該類提供了幾種方法來肯定字符的類別(小寫字母、數字等),並將字符從大寫轉換爲小寫,反之亦然
Character在 jdk8中,   基於版本Unicode6.0.2 標準
Character 類的方法和數據是經過 UnicodeData 文件中的信息定義的,
該文件是 Unicode Consortium 維護的 Unicode Character Database 的一部分
此文件指定了各類屬性,其中包括每一個已定義 Unicode 代碼點或字符範圍的名稱和常規類別
此文件及其描述可從 Unicode Consortium 得到,網址以下:
http://www.unicode.org
 
在Java中,char 數據類型(和 Character 對象封裝的值)基於原始的 Unicode 規範
將字符定義爲固定寬度的 16 位實體
也就是說 char表示UTF-16編碼的代碼單元
對於0號平面來講,一個碼點使用一個代碼單元
對於輔助平面,那麼一個碼點將會是兩個代碼單元
 
在Unicode簡介中,咱們有說到,一個字符在Unicode字符集中的二進制值稱爲代碼點
在UTF-16編碼中,0號平面內,一個碼點16位表示,稱之爲一個代碼單元
 
總結下就是:
Unicode字符集中,一個字符對應一個代碼點
UTF-16中,16位數表示的是一個代碼單元
那麼在0 號平面內,一個代碼單元就可以表示一個代碼點
可是在輔助平面,一個代碼點須要兩個代碼單元
 
java中的char就是UTF-16中的代碼單元
因此說,一個char表示一個代碼單元,可能並非一個字符
實在理解不了的話,就能夠記住,有些字符須要兩個char表示,一個char可能僅僅是某個字符的一半
 
 
Unicode字符數據庫(Unicode Character Database UCD  )
是由許多列出Unicode字符屬性和相關數據的數據文件組成
能夠查看http://www.unicode.org/ucd/  瞭解UCD的相關信息
查看
https://www.unicode.org/reports/tr44/#Property_Values
中的Property Value Lists章節
General Category Values以及Bidirectional Class Values章節瞭解
 
Character中定義了大量的常量,其實就是對於這兩個章節信息的描述
 
能夠簡單地理解爲是字符的屬性
好比一個字符多是大寫字母,多是小寫字母這樣子
好比getType方法就是專門用來返回屬性的,根據這個屬性進而能夠推斷出更多的信息就像下面的的例子這樣
 
 

 

image_5bc67cf2_71d7
image_5bc67cf2_1a12
 
Unicode想要深刻研究,也是一門學問,此處再也不繼續深刻,精力有限
對於Character咱們只須要記住
Character 類的方法和數據是經過 UnicodeData 文件中的信息定義的
char 數據類型(和 Character 對象封裝的值)基於原始的 Unicode 規範
提供的方法和數據也是基於Unicode規範來的
他將字符定義爲固定寬度的 16 位實體,也就是隻能表示一個代碼單元
而Unicode也多是有兩個代碼單元組成
也就是一個代碼單元可能完整的表示了一個代碼點,也多是一個代碼點的一部分
除非你真的有必要對UTF-16中的代碼單元進行操做,
不然最好不要在程序中使用char類型的緣由
緣由很簡單,一個char並不必定可以表明一個字符,可能只是一半字符
 
接下來對Character的基礎方法進行介紹,過於深刻Unicode的方法再也不說明
有興趣的能夠研究下

經常使用屬性

去掉上面說到的通用類別常量信息,還有如下屬性
無符號二進制形式表示 char 值的位數 public static final int SIZE = 16;
無符號二進制形式表示 char 值的字節數 public static final int BYTES = SIZE / Byte.SIZE;
表示基本類型 char 的 Class 實例 public static final Class<Character> TYPE = (Class<Character>) Class.getPrimitiveClass("char");
常量值是 char 類型的最小值,即 '\u0000' public static final char MIN_VALUE = '\u0000';
常量值是 char 類型的最大值,即 '\uFFFF' public static final char MAX_VALUE = '\uFFFF'
Unicode代碼點的最小值 public static final int MIN_CODE_POINT = 0x000000;
Unicode代碼點的最大值 public static final int MAX_CODE_POINT = 0X10FFFF;
UTF-16 編碼中的 Unicode 高代理項代碼單元的最小值 public static final char MIN_HIGH_SURROGATE = '\uD800';
UTF-16 編碼中的 Unicode 高代理項代碼單元的最大值 public static final char MAX_HIGH_SURROGATE = '\uDBFF';
UTF-16 編碼中的 Unicode 低代理項代碼單元的最小值 public static final char MIN_LOW_SURROGATE  = '\uDC00'
UTF-16 編碼中的 Unicode 低代理項代碼單元的最大值 public static final char MAX_LOW_SURROGATE  = '\uDFFF'
代理項的最小值
也就是高代理項的最小值
public static final char MIN_SURROGATE = MIN_HIGH_SURROGATE;
代理項的最大值
也就是低代理項的最大值
public static final char MAX_SURROGATE = MAX_LOW_SURROGATE;
增補代碼點的最小值
也就是除了0號平面的第一個值
public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x010000
可用於與字符串相互轉換的最大基數 public static final int MAX_RADIX = 36;
可用於與字符串相互轉換的最小基數 public static final int MIN_RADIX = 2
 
能夠看得出來,即便去掉了那些通用類別的常量,剩下的信息仍舊是對Unicode編碼的描述
只要看過了前文的Unicode的簡介,很好理解

構造方法

Character(char) 只有一種形式的構造方法
直接設置value的值
image_5bc67cf2_352c

經常使用方法

比較

compare(char, char) image_5bc67cf2_462b
看起來可能會有人以爲奇怪,怎麼還能直接減法?
其實char不就是一個UTF-16的代碼單元麼,他不就是一個十六進制數麼
以下圖所示,0x0058 - 0x002B 獲得的值的十進制就是45
image_5bc67cf2_5336
比較的也就是先後順序了
compareTo(Character) 實例方法
藉助於靜態方法
image_5bc67cf2_772b

valueOf    

系列 包裝 基本類型 爲 對象
valueOf系列一直都是將基本類型包裝爲對象類型,此處也是如此
Character也是有緩存的
image_5bc67cf2_487e

XXXValue 

獲取 基本類型值
charValue() 直接返回基本類型數據
image_5bc67cf2_1a1
 

toString 

藉助於String.valueOf方法包裝轉換
image_5bc67cf2_2d97

equals

重寫了equals方法,比較的是實際的對象中的value值
image_5bc67cf2_29b1
 

hashcode

直接返回value的int值
image_5bc67cf2_69e9
  

reverseBytes

 
public static char reverseBytes(char ch)
character也有翻轉字節轉換的方法
image_5bc67cf3_389d
 
再剩下就是Unicode更增強相關的方法了,簡單介紹下
 

getType

獲取字符在Unicode中的屬性類別信息
 
image_5bc67cf3_579b
再次強調,一個char只是一個代碼單元,本質是16位   因此參數類型爲char時,顯然不能支持輔助平面內的字符
顯然,int的範圍徹底足夠,能夠支持BMP和輔助平面
 
獲取到的屬性信息在很多針對於Unicode的處理中,將會頗有用
好比
image_5bc67cf3_6dc0

toChars

將指定的代碼點,保存到char數組
一個是保存到指定數組,一個是建立一個新的數組
public static
int toChars(int codePoint, char[] dst, int dstIndex)
保存到指定的數組的指定位置
若是0號平面內   dst[dstIndex] 中存儲相同的值,並返回 1
若是輔助平面   dst[dstIndex]高代理 dst[dstIndex+1]低代理返回2
public static
char[] toChars(int codePoint)
返回一個char數組保存指定代碼點
image_5bc67cf3_549e
 

codePointCount

返回代碼點的數量,兩種形式
codePointCount(CharSequence, int, int)
codePointCount(char[], int, int)
時刻記住,char是代碼單元,一個代碼點可能一個或者兩個代碼單元
image_5bc67cf3_5c0d
 

offsetByCodePoints

計算偏移指定個個數的代碼點後的索引
仍是那句話,char是代碼單元,一個代碼點可能一個或者兩個代碼單元
若是一個代碼點一個代碼單元,偏移多少個,那麼下標索引就是日後移動多少個了
惋惜,一個代碼點可能一個也可能兩個代碼單元
因此纔有了這個方法
 
以第一個方法爲例
就是說,給你一個數組,  而後又給了你start 和count,在這個子數組的範圍內
從index這個下標開始(顯然index應該位於start和start+count之間的,不然越界異常)
日後數codePointOffset 個代碼點,而後看看到底下標序號是多少,返回給調用者
返回的值可能就是index+codePointOffset  也可能大於index+codePointOffset
public static int offsetByCodePoints(char[] a,
                                     int start,
                                     int count,
                                     int index,
                                     int codePointOffset)
public static int offsetByCodePoints(CharSequence seq,
                                     int index,
                                     int codePointOffset)
 

codePointAt

獲取指定位置的代碼點
基本邏輯,若是第一個代碼單元的值在高代理區,下一個索引還小於數組的長度,而且下一個索引的地方是低代理區,那麼返回這個代碼點
不然,就是單純的返回這個代碼單元
說白了就是我能力範圍內就給你,不然就給你我有的那一半 第三個limit是範圍,其餘的範圍默認就是數組內
 
public static int codePointAt(char[] a, int index)
public static int codePointAt(CharSequence seq, int index)
public static int codePointAt(char[] a, int index, int limit )
看下下面這個例子,0x1f310上面也看到了,使用兩個代碼單元
chars保存了他的兩個代碼單元
chars1 只有一個元素,那就是0x1f310 的高代理位
image_5bc67cf3_29d8
 

codePointBefore

codePointBefore  和 codePointAt幾乎是一回事情,只不過是指定位置的前面
若是指定位置前面一個 index-1 處是一個低代理,並且更前面的一個index-2 是一個數組內的有效數據
那麼,就返回代碼點
不然就返回一個單元
start至關於限定了數組的範圍,原本index-2>=0 就行了 如今index-2須要 >=start了
public static int codePointBefore(CharSequence seq,int index)
public static int codePointBefore(char[] a, int index)
public static int codePointBefore(char[] a, int index,  int start )
 

charCount

public static int charCount(int codePoint)
肯定表示指定字符(Unicode 代碼點)所需的 char 值的數量。若是指定字符等於或大於 0x10000,則該方法返回的值爲 2。不然,該方法返回的值爲 1
從代碼能夠看得出來,他就是直接查看代碼點的值簡單的計算
並無確認是不是有效字符
image_5bc67cf3_ba0
 

toLowerCase  / toUpperCase /toTitleCase

都是使用取自 UnicodeData 文件的大小寫映射信息將字符(Unicode 代碼點)進行參數轉換
lowCase就是轉換爲小寫
UpperCase就是轉換爲大寫
TitleCase就是首字母大寫
又是兩個版本的參數,一個char 一個int 仍是老樣子,char不支持輔助平面
toLowerCase(char)
toLowerCase(int)
toUpperCase(char)
toUpperCase(int)
toTitleCase(char)
toTitleCase(int)
 

代碼點獲取

public static char highSurrogate(int codePoint) 返回代碼點的高代理
若是不是輔助平面的字符,返回未知char
public static char lowSurrogate(int codePoint) 返回代碼點的低代理
若是不是輔助平面的字符,返回未知char
 

代理位信息判斷

public static boolean isSurrogate(char ch) 是否代理部分
public static boolean isSurrogatePair(char high, char low) 是不是代理對
public static boolean isHighSurrogate(char ch) 是不是高代理
public static boolean isLowSurrogate(char ch) 是不是低代理
 

代碼點信息的校驗

public static boolean isValidCodePoint(int codePoint)  是不是合法的代碼點
肯定指定的代碼點是否爲從 0x0000 到 0x10FFFF 範圍以內的有效 Unicode 代碼點值
public static boolean isBmpCodePoint(int codePoint) 是否位於0號平面,是的話就可使用一個char表示了
public static boolean isSupplementaryCodePoint(int codePoint) 是否位於輔助平面 輔助平面必然須要使用兩個char
 
 

toCodePoint(char, char)

public static int toCodePoint(char high,char low)
將指定的代理項對轉換爲其增補代碼點值。該方法沒有驗證指定的代理項對
若有必要,調用者必須使用 isSurrogatePair 驗證它
就是高代理 低代理的合併
 

isXXX   系列

isXXX系列就是校驗XXX的信息是否爲真
大多兩個版本,一個是char 一個是int
仍是老樣子,char僅僅支持0號平面
小寫?
isLowerCase(char)
isLowerCase(int)
大寫?
isUpperCase(char)
isUpperCase(int)
首字母大寫?
isTitleCase(char)
isTitleCase(int)
數字?
isDigit(char)
isDigit(int)
被定義爲 Unicode 中的字符?
isDefined(char)
isDefined(int)
字母?
isLetter(char)
isLetter(int)
字母或數字?
isLetterOrDigit(char)
isLetterOrDigit(int)
是否可以做爲 Java 標識符中的首字符?
isJavaIdentifierStart(char)
isJavaIdentifierStart(int)
是否可以做爲 Java 標識符中的首字符之外的字符?
isJavaIdentifierPart(char)
isJavaIdentifierPart(int)
是否容許做爲 Unicode 標識符中的首字符?
isUnicodeIdentifierStart(char)
isUnicodeIdentifierStart(int)
是否容許做爲 Unicode 標識符中的首字符之外的字符?
isUnicodeIdentifierPart(char)
isUnicodeIdentifierPart(int)
是不是 Java 標識符或 Unicode 標識符中可忽略的一個字符?
isIdentifierIgnorable(char)
isIdentifierIgnorable(int)
空白字符?
isSpaceChar(char)
isSpaceChar(int)
Java 標準是否爲空白字符?
isWhitespace(char)
isWhitespace(int)
ISO 控制字符?
isISOControl(char)
isISOControl(int)
字母?
isAlphabetic(int)   
中日越韓文字?
isIdeographic(int)
依據 Unicode 規範是否對稱?
isMirrored(char)
isMirrored(int)
 
isAlphabetic 和 isLetter 相似,  可是類型範圍有差異
isAlphabetic範圍更大
UPPERCASE_LETTER   LOWERCASE_LETTER   TITLECASE_LETTER   MODIFIER_LETTER   OTHER_LETTER  LETTER_NUMBER   
UPPERCASE_LETTER   LOWERCASE_LETTER   TITLECASE_LETTER   MODIFIER_LETTER   OTHER_LETTER   
 
返回使用指定基數的   字符 ch/Unicode 代碼點 的數值
public static int digit(char ch, int radix)
public static int digit(int codePoint, int radix)
肯定使用指定基數的特定數字的字符表示形式 public static char forDigit(int digit, int radix)
返回給定字符的 Unicode 方向屬性
public static byte getDirectionality(char ch)
public static byte getDirectionality(int codePoint)
返回指定的 Unicode 字符/Unicode 代碼點 表示的int值
public static int getNumericValue(char ch)
public static int getNumericValue(int codePoint)
返回指定字符codePoint的Unicode名稱,若是代碼點未被分配,則返回null public static String getName(int codePoint)
 
感覺下getName
image_5bc67cf3_5e79
 

總結

 
Java中的char 也就是Character中包裝的數據
他們是UTF-16中的代碼單元
一個Unicode字符集的數值叫作一個代碼點
因此一個字符多是一個char也多是兩個char
因此,除非真的有必要,但願對UTF16的代碼單元進行處理,不要使用char類型,使用其餘的高級類型好比String
char就是Unicode UTF-16在程序中的應用
想要理解char就必須理解Unicode和UTF16
Character中的定義的變量以及方法,大多都是和他們息息相關的
相關文章
相關標籤/搜索