本系列文章經補充和完善,已修訂整理成書《Java編程的邏輯》(馬俊昌著),由機械工業出版社華章分社出版,於2018年1月上市熱銷,讀者好評如潮!各大網店和書店有售,歡迎購買:京東自營連接 html
![]()
本節探討Character類,它的基本用法咱們在包裝類第一節已經介紹了,本節再也不贅述。Character類除了封裝了一個char外,還有什麼可介紹的呢?它有不少靜態方法,封裝了Unicode字符級別的各類操做,是Java文本處理的基礎,注意不是char級別,Unicode字符並不等同於char,本節詳細介紹這些方法以及相關的Unicode知識。java
在介紹這些方法以前,咱們須要回顧一下字符在Java中的表示方法,咱們在第六節、第七節、第八節介紹過編碼、Unicode、char等知識,咱們先簡要回顧一下。git
Unicode給世界上每一個字符分配了一個編號,編號範圍從0x000000到0x10FFFF。編號範圍在0x0000到0xFFFF之間的字符,爲經常使用字符集,稱BMP(Basic Multilingual Plane)字符。編號範圍在0x10000到0x10FFFF之間的字符叫作增補字符(supplementary character)。編程
Unicode主要規定了編號,但沒有規定如何把編號映射爲二進制,UTF-16是一種編碼方式,或者叫映射方式,它將編號映射爲兩個或四個字節,對BMP字符,它直接用兩個字節表示,對於增補字符,使用四個字節,前兩個字節叫高代理項(high surrogate),範圍從0xD800到0xDBFF,後兩個字節叫低代理項(low surrogate),範圍從0xDC00到0xDFFF,UTF-16定義了一個公式,能夠將編號與四字節表示進行相互轉換。數組
Java內部採用UTF-16編碼,char表示一個字符,但只能表示BMP中的字符,對於增補字符,須要使用兩個char表示,一個表示高代理項,一個表示低代理項。bash
使用int能夠表示任意一個Unicode字符,低21位表示Unicode編號,高11位設爲0。整數編號在Unicode中通常稱爲代碼點(Code Point),表示一個Unicode字符,與之相對,還有一個詞代碼單元(Code Unit)表示一個char。微信
Character類中有不少相關靜態方法,讓咱們來看一下。函數
判斷一個int是否是一個有效的代碼單元:編碼
public static boolean isValidCodePoint(int codePoint) 複製代碼
小於等於0x10FFFF的爲有效,大於的爲無效。spa
判斷一個int是否是BMP字符:
public static boolean isBmpCodePoint(int codePoint) 複製代碼
小於等於0xFFFF的爲BMP字符,大於的不是。
判斷一個int是否是增補字符:
public static boolean isSupplementaryCodePoint(int codePoint) 複製代碼
0x010000和0X10FFFF之間的爲增補字符。
判斷char是不是高代理項:
public static boolean isHighSurrogate(char ch) 複製代碼
0xD800到0xDBFF爲高代理項。
判斷char是否爲低代理項:
public static boolean isLowSurrogate(char ch) 複製代碼
0xDC00到0xDFFF爲低代理項。
判斷char是否爲代理項:
public static boolean isSurrogate(char ch) 複製代碼
char爲低代理項或高代理項,則返回true。
判斷兩個字符high和low是否分別爲高代理項和低代理項:
public static boolean isSurrogatePair(char high, char low) 複製代碼
判斷一個代碼單元由幾個char組成:
public static int charCount(int codePoint) 複製代碼
增補字符返回2,BMP字符返回1。
除了簡單的檢查外,Character類中還有不少方法,進行code point與char的相互轉換。
根據高代理項high和低代理項low生成代碼單元:
public static int toCodePoint(char high, char low) 複製代碼
這個轉換有個公式,這個方法封裝了這個公式。
根據代碼單元生成char數組,即UTF-16表示:
public static char[] toChars(int codePoint)
複製代碼
若是code point爲BMP字符,則返回的char數組長度爲1,若是爲增補字符,長度爲2,char[0]爲高代理項,char[1]爲低代理項。
將代碼單元轉換爲char數組:
public static int toChars(int codePoint, char[] dst, int dstIndex) 複製代碼
與上面方法相似,只是結果存入指定數組dst的指定位置index。
對增補字符code point,生成高代理項和低代理項:
public static char lowSurrogate(int codePoint) public static char highSurrogate(int codePoint) 複製代碼
Character包含若干方法,以方便按照code point來處理char數組或序列。
返回char數組a中從offset開始count個char包含的code point個數:
public static int codePointCount(char[] a, int offset, int count) 複製代碼
好比說,以下代碼輸出爲2,char個數爲3,但code point爲2。
char[] chs = new char[3];
chs[0] = '馬';
Character.toChars(0x1FFFF, chs, 1);
System.out.println(Character.codePointCount(chs, 0, 3));
複製代碼
除了接受char數組,還有一個重載的方法接受字符序列CharSequence:
public static int codePointCount(CharSequence seq, int beginIndex, int endIndex) 複製代碼
CharSequence是一個接口,它的定義以下所示:
public interface CharSequence {
int length();
char charAt(int index);
CharSequence subSequence(int start, int end);
public String toString();
}
複製代碼
它與一個char數組是相似的,有length方法,有charAt方法根據索引獲取字符,String類就實現了該接口。
返回char數組或序列中指定索引位置的code point:
public static int codePointAt(char[] a, int index) public static int codePointAt(char[] a, int index, int limit) public static int codePointAt(CharSequence seq, int index) 複製代碼
若是指定索引位置爲高代理項,下一個位置爲低代理項,則返回兩項組成的code point,檢查下一個位置時,下一個位置要小於limit,沒傳limit時,默認爲a.length。
返回char數組或序列中指定索引位置以前的code point:
public static int codePointBefore(char[] a, int index) public static int codePointBefore(char[] a, int index, int start) public static int codePointBefore(CharSequence seq, int index) 複製代碼
與codePointAt不一樣,codePoint是日後找,codePointBefore是往前找,若是指定位置爲低代理項,且前一個位置爲高代理項,則返回兩項組成的code point,檢查前一個位置時,前一個位置要大於等於start,沒傳start時,默認爲0。
根據code point偏移數計算char索引:
public static int offsetByCodePoints(char[] a, int start, int count, int index, int codePointOffset) public static int offsetByCodePoints(CharSequence seq, int index, int codePointOffset) 複製代碼
若是字符數組或序列中沒有增補字符,返回值爲index+codePointOffset,若是有增補字符,則會將codePointOffset看作code point偏移,轉換爲字符偏移,start和count取字符數組的子數組。
好比,咱們看以下代碼:
char[] chs = new char[3];
Character.toChars(0x1FFFF, chs, 1);
System.out.println(Character.offsetByCodePoints(chs, 0, 3, 1, 1));
複製代碼
輸出結果爲3,index和codePointOffset都爲1,但第二個字符爲增補字符,一個code point偏移是兩個char偏移,因此結果爲3。
咱們以前說,Unicode主要是給每一個字符分配了一個編號,其實,除了分配編號以外,還分配了一些屬性,Character類封裝了對Unicode字符屬性的檢查和操做,咱們來看一些主要的屬性。
獲取字符類型(general category):
public static int getType(int codePoint) public static int getType(char ch) 複製代碼
Unicode給每一個字符分配了一個類型,這個類型是很是重要的,不少其餘檢查和操做都是基於這個類型的。
getType方法的參數能夠是int類型的code point,也能夠是char類型,char只能處理BMP字符,而int能夠處理全部字符,Character類中不少方法都是既能夠接受int,也能夠接受char,後續只列出int類型的方法。
返回值是int,表示類型,Character類中定義了不少靜態常量表示這些類型,下表列出了一些字符,type值,以及Character類中常量的名稱:
|字符 |type值 | 常量名稱 | ------------- |:-------------:| |'A' |1 |UPPERCASE_LETTER| |'a' |2 |LOWERCASE_LETTER| |'馬' |5 |OTHER_LETTER| |'1' |9 |DECIMAL_DIGIT_NUMBER| |' ' |12 |SPACE_SEPARATOR| |'\n' |15 |CONTROL| |'-' |20 |DASH_PUNCTUATION| |'{' |21 |START_PUNCTUATION| |'_' |23 |CONNECTOR_PUNCTUATION| |'&' |24 |OTHER_PUNCTUATION| |'<' |25 |MATH_SYMBOL| |'$' |26 |CURRENCY_SYMBOL|
檢查字符是否在Unicode中被定義:
public static boolean isDefined(int codePoint) 複製代碼
每一個被定義的字符,其getType()返回值都不爲0,若是返回值爲0,表示無定義。注意與isValidCodePoint的區別,後者只要數字不大於0x10FFFF都返回true。
檢查字符是否爲數字:
public static boolean isDigit(int codePoint) 複製代碼
getType()返回值爲DECIMAL_DIGIT_NUMBER的字符爲數字,須要注意的是,不光字符'0','1',...'9'是數字,中文全角字符的0到9,即'0','1','9'也是數字。好比說:
char ch = '9'; //中文全角數字
System.out.println((int)ch+","+Character.isDigit(ch));
複製代碼
輸出爲:
65305,true
複製代碼
全角字符的9,Unicode編號爲65305,它也是數字。
檢查是否爲字母(Letter):
public static boolean isLetter(int codePoint) 複製代碼
若是getType()的返回值爲下列之一,則爲Letter:
UPPERCASE_LETTER
LOWERCASE_LETTER
TITLECASE_LETTER
MODIFIER_LETTER
OTHER_LETTER
複製代碼
除了TITLECASE_LETTER和MODIFIER_LETTER,其餘咱們上面已經看到過了,而這兩個平時碰到的也比較少,就不介紹了。
檢查是否爲字母或數字
public static boolean isLetterOrDigit(int codePoint) 複製代碼
只要其中之一返回true就返回true。
檢查是否爲字母(Alphabetic)
public static boolean isAlphabetic(int codePoint) 複製代碼
這也是檢查是否爲字母,與isLetter的區別是,isLetter返回true時,isAlphabetic也必然返回true,此外,getType()值爲LETTER_NUMBER時,isAlphabetic也返回true,而isLetter返回false。Letter_NUMBER中常見的字符有羅馬數字字符,如:'Ⅰ','Ⅱ','Ⅲ','Ⅳ'。
檢查是否爲空格字符
public static boolean isSpaceChar(int codePoint) 複製代碼
getType()值爲SPACE_SEPARATOR,LINE_SEPARATOR和PARAGRAPH_SEPARATOR時,返回true。這個方法其實並不經常使用,由於它只能嚴格匹配空格字符自己,不能匹配實際產生空格效果的字符,如tab控制鍵'\t'。
更經常使用的檢查空格的方法
public static boolean isWhitespace(int codePoint) 複製代碼
'\t','\n',全角空格' ',和半角空格' '的返回值都爲true。
檢查是否爲小寫字符
public static boolean isLowerCase(int codePoint) 複製代碼
常見的主要就是小寫英文字母a到z。
檢查是否爲大寫字符
public static boolean isUpperCase(int codePoint) 複製代碼
常見的主要就是大寫英文字母A到Z。
檢查是否爲表意象形文字
public static boolean isIdeographic(int codePoint) 複製代碼
大部分中文都返回爲true。
檢查是否爲ISO 8859-1編碼中的控制字符
public static boolean isISOControl(int codePoint) 複製代碼
咱們在第6節介紹過,0到31,127到159表示控制字符。
檢查是否可做爲Java標示符的第一個字符
public static boolean isJavaIdentifierStart(int codePoint) 複製代碼
Java標示符是Java中的變量名、函數名、類名等,字母(Alphabetic),美圓符號($),下劃線(_)可做爲Java標示符的第一個字符,但數字字符不能夠。
檢查是否可做爲Java標示符的中間字符
public static boolean isJavaIdentifierPart(int codePoint) 複製代碼
相比isJavaIdentifierStart,主要多了數字字符,中間能夠有數字。
檢查是否爲鏡像(mirrowed)字符
public static boolean isMirrored(int codePoint) 複製代碼
常見鏡像字符有( ) { } < > [ ],都有對應的鏡像。
Unicode除了規定字符屬性外,對有大小寫對應的字符,還規定了其對應的大小寫,對有數值含義的字符,也規定了其數值。
咱們先來看大小寫,Character有兩個靜態方法,對字符進行大小寫轉換:
public static int toLowerCase(int codePoint) public static int toUpperCase(int codePoint) 複製代碼
這兩個方法主要針對英文字符a-z和A-Z, 例如:toLowerCase('A')返回'a',toUpperCase('z')返回'Z'。
返回一個字符表示的數值:
public static int getNumericValue(int codePoint) 複製代碼
字符'0'到'9'返回數值0到9,對於字符a到z,不管是小寫字符仍是大寫字符,不管是普通英文仍是中文全角,數值結果都是10到35,例如,以下代碼的輸出結果是同樣的,都是10。
System.out.println(Character.getNumericValue('A')); //全角大寫A
System.out.println(Character.getNumericValue('A'));
System.out.println(Character.getNumericValue('a')); //全角小寫a
System.out.println(Character.getNumericValue('a'));
複製代碼
返回按給定進製表示的數值:
public static int digit(int codePoint, int radix) 複製代碼
radix表示進制,常見的有2/8/10/16進制,計算方式與getNumericValue相似,只是會檢查有效性,數值須要小於radix,若是無效,返回-1,例如:
digit('F',16)返回15,是有效的,但digit('G',16)就無效,返回-1。
返回給定數值的字符形式
public static char forDigit(int digit, int radix) 複製代碼
與digit(int codePoint, int radix)相比,進行相反轉換,若是數字無效,返回'\0'。例如,Character.forDigit(15, 16)返回'F'。
與Integer相似,Character也有按字節翻轉:
public static char reverseBytes(char ch) 複製代碼
例如,翻轉字符0x1234:
System.out.println(Integer.toHexString(
Character.reverseBytes((char)0x1234)));
複製代碼
輸出爲3412。
本節詳細介紹了Characer類以及相關的Unicode知識,Character類在Unicode字符級別,而非char級別,封裝了字符的各類操做,經過將字符處理的細節交給Character類,其餘類就能夠在更高的層次上處理文本了。
至此,關於包裝類咱們就介紹完了。下一節,讓咱們在Character的基礎上,進一步探索字符串類String。
未完待續,查看最新文章,敬請關注微信公衆號「老馬說編程」(掃描下方二維碼),深刻淺出,老馬和你一塊兒探索Java編程及計算機技術的本質。用心原創,保留全部版權。