淺談「isAlphabetic()」與「isLetter()」的差異
目的
了解「Java API」中,「isAlphabetic()」和「isLetter()」兩者之間的差異。
概要
在程式開發的過程中,「判斷目標字元是否為英文字母。」是很常見的需求,而其解法常見的有「ASCII 法」和「正規表示式法」,其中「ASCII 法」是筆者比較常使用的方式,如下:
private boolean isEnglishCharByAscii(char c) {
return (c >= 65 && c <= 90) || (c >= 97 && c <= 122);
}
至於「正規表示式」的解法,呃,附上「傳送門:正規表示式」;小弟怕怕,恕小弟就不奉陪了。
言歸正傳,然而,不論是「ASCII 法」或是「正規表示式法」,其都還是需要自行實作,雖然這並不難,但是使用原生現成的 API,不是更優雅嗎?
事實上,在「Java」原生的「Character」類別中就存在著類似的方法,分別是「isAlphabetic()」和「isLetter()」,不過說來慚愧,雖然一直都知道有這兩個方法且都可以用來「判斷目標字元是否為英文字母。」,但惰性使得筆者一直沒有去探討其兩者的差異。
然而,明日復明日,今日,我們就來一探究竟。
正文
廢話不多說,官方文件直接刷起來,「isLetter()」:
簡單的說就是所有的字元都有「被分類」,而我們可以藉由「Character」類別中的「getType()」方法來取得字元「種類」,而若其返回的「種類別」為「UPPERCASE_LETTER」、「LOWERCASE_LETTER」、「TITLECASE_LETTER」、「MODIFIER_LETTER」或是「OTHER_LETTER」,則該字元就會被判定為「英文字元」。
簡單、清楚、明瞭…個屁?WTF,文是寫得非常清楚沒錯,但鬼才會知道那些「種類」是圓的還是扁的!
俗話說,天無絕人之路,既然在「isLetter()」找不到溫暖,我們拐個彎,從「isAlphabetic()」上下手,不囉唆,直接上文件「isAlphabetic()」,如下:
恩,結果就是,呃,符合的「種類」多了一項「LETTER_NUMBER」。
總結一下,至少,我們知道「isAlphabetic()」比「isLetter()」多涵蓋了一個種類的「字元」。
說實在的,官方文件的幫助並不大,經「Google」後,筆者找到了一篇相關文章,有網友在「StackOverFlow」發表的同樣的問題,如下:
內文中寫到:「『isLetter()』一定是『isAlphabetic()』,但反之就不一定,因為『isAlphabetic()』多涵蓋了一個『種類』的字元。」,這跟我們上述的一樣,但我想給各位讀者看的是下面這句:「就英文而言,這兩者並不會有任何差異,但建議使用「isLetter()」。
雖然這篇文章並沒有回答到我們的疑問,但至少,它已經提供了使用上的建議。
但筆者並不願意滿足於這樣的結果,經過一番搜尋,筆者終於找到了還算令人滿意的答案。
「Java 编程的邏輯」一書的作者「馬俊昌」在他的「部落格文章」中就有提到相關的知識,如下:
事實上,在編成的世界裡,只要提到「字元定義」、「字元屬性」、「字元類別」…等,基本上就撇不開「Unicode」的關係,同樣地,「字元種類的定義」,也是跟「Unicode」相關的。
還記得「LETTER_NUMBER」嗎?
就是「isAlphabetic()」比「isLetter()」多涵蓋的那個「種類」,在該文中就有提到「『LETTER_NUMBER』種類最常見的字元就是『羅馬數字的字符』。」,如下:
總結
最後筆者作個總結,身為台灣的程式設計師,事實上,我們鮮少使用到「英文」以外的字元作開發,因此,如上述,在使用上,我們僅需要知道:「就英文而言,這兩者並不會有任何差異,但建議使用「isLetter()」,這樣即可。
若各位讀者想認識更多有關「Character」類別的相關知識,我認為該篇文章是個很不錯的資源。
那本篇的介紹就到這篇了,收工囉!