原文引自:
http://java.sun.com/developer/technicalArticles/Intl/Supplementary/index_zh_CN.html作者:Sun Microsystems, Inc. 的 Norbert Lindenberg 和 Masayoshi Okutsu
2004 年 5 月
English: Supplementary Characters in the Java Platform
日本語: Java プラットフォームにおける補助文字のサポート
摘要
本文介紹 Java 平臺支持增補字符的方式。增補字符是 Unicode 標準中代碼點超出 U+FFFF 的字符,因此它們無法在 Java 編程語言中描述為單個的 16 位實體(例如 char
數據類型)。這些字符一般極少用,但是,有些會在諸如中文或日文人名中用到,因此,在東亞國家,政府應用程序通常會要求支持這些字符。
Java 平臺目前正在改進,以便支持對增補字符的處理,這種改進對現有的應用程序影響微乎其微。新的低層 API 在需要時能夠使用單個的字符運行。不過,大多數文本處理 API 均使用字符序列,例如 String
類或字符數組。現在,這些均解釋為 UTF-16 序列,而且,這些 API 實現已轉變為正確地處理增補字符。這些改進已融入 Java 2 平臺 5.0 版,標準版 (J2SE)。
除詳細解釋這些改進之外,本文同時為應用程序開發人員確定和實現必要的更改提供指導,以支持整個 Unicode 字符集的使用。
背景
Unicode 最初設計是作為一種固定寬度的 16 位字符編碼。在 Java 編程語言中,基本數據類型 char
初衷是通過提供一種簡單的、能夠包含任何字符的數據類型來充分利用這種設計的優點。不過,現在看來,16 位編碼的所有 65,536 個字符并不能完全表示全世界所有正在使用或曾經使用的字符。于是,Unicode 標準已擴展到包含多達 1,112,064 個字符。那些超出原來的 16 位限制的字符被稱作增補字符。Unicode 標準 2.0 版是第一個包含啟用增補字符設計的版本,但是,直到 3.1 版才收入第一批增補字符集。由于 J2SE 的 5.0 版必須支持 Unicode 標準 4.0 版,因此它必須支持增補字符。
對增補字符的支持也可能會成為東亞市場的一個普遍商業要求。政府應用程序會需要這些增補字符,以正確表示一些包含罕見中文字符的姓名。出版應用程序可能會需要這些增補字符,以表示所有的古代字符和變體字符。中國政府要求支持 GB18030(一種對整個 Unicode 字符集進行編碼的字符編碼標準),因此,如果是 Unicode 3.1 版或更新版本,則將包括增補字符。臺灣標準 CNS-11643 包含的許多字符在 Unicode 3.1 中列為增補字符。香港政府定義了一種針對粵語的字符集,其中的一些字符是 Unicode 中的增補字符。最后,日本的一些供應商正計劃利用增補字符空間中大量的專用空間收入 50,000 多個日文漢字字符變體,以便從其專有系統遷移至基于 Java 平臺的解決方案。
因此,Java 平臺不僅需要支持增補字符,而且必須使應用程序能夠方便地做到這一點。由于增補字符打破了 Java 編程語言的基礎設計構想,而且可能要求對編程模型進行根本性的修改,因此,Java Community Process 召集了一個專家組,以期找到一個適當的解決方案。該小組被稱為 JSR-204 專家組,使用 Unicode 增補字符支持的 Java 技術規范請求的編號。從技術上來說,該專家組的決定僅適用于 J2SE 平臺,但是由于 Java 2 平臺企業版 (J2EE) 處于 J2SE 平臺的最上層,因此它可以直接受益,我們期望 Java 2 平臺袖珍版 (J2ME) 的配置也采用相同的設計方法。
不過,在了解 JSR-204 專家組確定的解決方案之前,我們需要先理解一些術語。
代碼點、字符編碼方案、UTF-16:這些是指什么?
不幸的是,引入增補字符使字符模型變得更加復雜了。在過去,我們可以簡單地說“字符”,在一個基于 Unicode 的環境(例如 Java 平臺)中,假定字符有 16 位,而現在我們需要更多的術語。我們會盡量介紹得相對簡單一些 — 如需了解所有詳細的討論信息,您可以閱讀 Unicode 標準第 2 章或 Unicode 技術報告 17“字符編碼模型”。Unicode 專業人士可略過所有介紹直接參閱本部分中的最后定義。
字符是抽象的最小文本單位。它沒有固定的形狀(可能是一個字形),而且沒有值。“A”是一個字符,“€”(德國、法國和許多其他歐洲國家通用貨幣的標志)也是一個字符。
字符集是字符的集合。例如,漢字字符是中國人最先發明的字符,在中文、日文、韓文和越南文的書寫中使用。
編碼字符集是一個字符集,它為每一個字符分配一個唯一數字。Unicode 標準的核心是一個編碼字符集,字母“A”的編碼為 004116 和字符“€”的編碼為 20AC16。Unicode 標準始終使用十六進制數字,而且在書寫時在前面加上前綴“U+”,所以“A”的編碼書寫為“U+0041”。
代碼點是指可用于編碼字符集的數字。編碼字符集定義一個有效的代碼點范圍,但是并不一定將字符分配給所有這些代碼點。有效的 Unicode 代碼點范圍是 U+0000 至 U+10FFFF。Unicode 4.0 將字符分配給一百多萬個代碼點中的 96,382 代碼點。
增補字符是代碼點在 U+10000 至 U+10FFFF 范圍之間的字符,也就是那些使用原始的 Unicode 的 16 位設計無法表示的字符。從 U+0000 至 U+FFFF 之間的字符集有時候被稱為基本多語言面 (BMP)。因此,每一個 Unicode 字符要么屬于 BMP,要么屬于增補字符。
字符編碼方案是從一個或多個編碼字符集到一個或多個固定寬度代碼單元序列的映射。最常用的代碼單元是字節,但是 16 位或 32 位整數也可用于內部處理。UTF-32、UTF-16 和 UTF-8 是 Unicode 標準的編碼字符集的字符編碼方案。
UTF-32 即將每一個 Unicode 代碼點表示為相同值的 32 位整數。很明顯,它是內部處理最方便的表達方式,但是,如果作為一般字符串表達方式,則要消耗更多的內存。
UTF-16 使用一個或兩個未分配的 16 位代碼單元的序列對 Unicode 代碼點進行編碼。值 U+0000 至 U+FFFF 編碼為一個相同值的 16 位單元。增補字符編碼為兩個代碼單元,第一個單元來自于高代理范圍(U+D800 至 U+DBFF),第二個單元來自于低代理范圍(U+DC00 至 U+DFFF)。這在概念上可能看起來類似于多字節編碼,但是其中有一個重要區別:值 U+D800 至 U+DFFF 保留用于 UTF-16;沒有這些值分配字符作為代碼點。這意味著,對于一個字符串中的每個單獨的代碼單元,軟件可以識別是否該代碼單元表示某個單單元字符,或者是否該代碼單元是某個雙單元字符的第一個或第二單元。這相當于某些傳統的多字節字符編碼來說是一個顯著的改進,在傳統的多字節字符編碼中,字節值 0x41 既可能表示字母“A”,也可能是一個雙字節字符的第二個字節。
UTF-8 使用一至四個字節的序列對編碼 Unicode 代碼點進行編碼。U+0000 至 U+007F 使用一個字節編碼,U+0080 至 U+07FF 使用兩個字節,U+0800 至 U+FFFF 使用三個字節,而 U+10000 至 U+10FFFF 使用四個字節。UTF-8 設計原理為:字節值 0x00 至 0x7F 始終表示代碼點 U+0000 至 U+007F(Basic Latin 字符子集,它對應 ASCII 字符集)。這些字節值永遠不會表示其他代碼點,這一特性使 UTF-8 可以很方便地在軟件中將特殊的含義賦予某些 ASCII 字符。
下表所示為幾個字符不同表達方式的比較:
Unicode 代碼點 | U+0041 | U+00DF | U+6771 | U+10400 |
表示字形 |  |  |  |  |
UTF-32 代碼單元 | | | | |
UTF-16 代碼單元 | | | | |
UTF-8 代碼單元 | | | | |
另外,本文在許多地方使用術語字符序列或 char
序列概括 Java 2 平臺識別的所有字符序列的容器:char[]
, java.lang.CharSequence
的實現(例如 String
類),和 java.text.CharacterIterator
的實現。
這么多術語。它們與在 Java 平臺中支持增補字符有什么關系呢?
Java 平臺中增補字符的設計方法
JSR-204 專家組必須作出的主要決定是如何在 Java API 中表示增補字符,包括單個字符和所有形式的字符序列。專家組考慮并排除了多種方法:
- 重新定義基本類型
char
,使其具有 32 位,這樣也會使所有形式的 char
序列成為 UTF-32 序列。
- 在現有的 16 位類型
char
的基礎上,為字符引入一種新的 32 位基本類型(例如,char32
)。所有形式的 Char 序列均基于 UTF-16。
- 在現有的 16 位類型
char
的基礎上,為字符引入一種新的 32 位基本類型(例如,char32
)。String
和 StringBuffer
接受并行 API,并將它們解釋為 UTF-16 序列或 UTF-32 序列;其他 char
序列繼續基于 UTF-16。
- 使用
int
表示增補的代碼點。String
和 StringBuffer
接受并行 API,并將它們解釋為 UTF-16 序列或 UTF-32 序列;其他 char
序列繼續基于 UTF-16。
- 使用代理
char
對,表示增補代碼點。所有形式的 char
序列基于 UTF-16。
- 引入一種封裝字符的類。
String
和 StringBuffer
接受新的 API,并將它們解釋為此類字符的序列。
- 使用一個
CharSequence
實例和一個索引的組合表示代碼點。
在這些方法中,一些在早期就被排除了。例如,重新定義基本類型 char
,使其具有 32 位,這對于全新的平臺可能會非常有吸引力,但是,對于 J2SE 來說,它會與現有的 Java 虛擬機1、序列化和其他接口不兼容,更不用說基于 UTF-32 的字符串要使用兩倍于基于 UTF-16 的字符串的內存了。添加一種新類型的 char32
可能會簡單一些,但是仍然會出現虛擬機和序列化方面的問題。而且,語言更改通常需要比 API 更改有更長的提前期,因此,前面兩種方法會對增補字符支持帶來無法接受的延遲。為了在余下的方法中篩選出最優方案,實現小組使用四種不同的方法,在大量進行低層字符處理的代碼(java.util.regex
包)中實現了對增補字符支持,并對這四種方法的難易程度和運行表現進行了比較。
最終,專家組確定了一種分層的方法:
- 使用基本類型
int
在低層 API 中表示代碼點,例如 Character
類的靜態方法。
- 將所有形式的
char
序列均解釋為 UTF-16 序列,并促進其在更高層級 API 中的使用。
- 提供 API,以方便在各種
char
和基于代碼點的表示法之間的轉換。
在需要時,此方法既能夠提供一種概念簡明且高效的單個字符表示法,又能夠充分利用通過改進可支持增補字符的現有 API。同時,還能夠促進字符序列在單個字符上的應用,這一點一般對于國際化的軟件很有好處。
在這種方法中,一個 char
表示一個 UTF-16 代碼單元,這樣對于表示代碼點有時并不夠用。您會注意到,J2SE 技術規范現在使用術語代碼點和 UTF-16 代碼單元(表示法是相關的)以及通用術語字符(表示法與該討論沒有關系)。API 通常使用名稱 codePoint
描述表示代碼點的類型 int
的變量,而 UTF-16 代碼單元的類型當然為 char
。
我們將在下面兩部分中了解到 J2SE 平臺的實質變化 — 其中一部分介紹單個代碼點的低層 API,另一部分介紹采用字符序列的高層接口。
開放的增補字符:基于代碼點的 API
新增的低層 API 分為兩大類:用于各種 char
和基于代碼點的表示法之間轉換的方法和用于分析和映射代碼點的方法。
最基本的轉換方法是 Character.toCodePoint(char?high, char?low)
(用于將兩個 UTF-16 代碼單元轉換為一個代碼點)和 Character.toChars(int?codePoint)
(用于將指定的代碼點轉換為一個或兩個 UTF-16 代碼單元,然后封裝到一個 char[]
內。不過,由于大多數情況下文本以字符序列的形式出現,因此,另外提供 codePointAt
和 codePointBefore
方法,用于將代碼點從各種字符序列表示法中提取出來:Character.codePointAt(char[]?a, int?index)
和 String.codePointBefore(int index)
是兩種典型的例子。在將代碼點插入字符序列時,大多數情況下均有一些針對 StringBuffer
和 StringBuilder
類的 appendCodePoint(int codePoint)
方法,以及一個用于提取表示代碼點的 int[]
的 String
構建器。
幾種用于分析代碼單元和代碼點的方法有助于轉換過程:Character 類中的 isHighSurrogate
和 isLowSurrogate
方法可以識別用于表示增補字符的 char
值;charCount(int codePoint)
方法可以確定是否需要將某個代碼點轉換為一個或兩個 char
。
但是,大多數基于代碼點的方法均能夠對所有 Unicode 字符實現基于 char
的舊方法對 BMP 字符所實現的功能。以下是一些典型例子:
Character.isLetter(int codePoint)
可根據 Unicode 標準識別字母。
Character.isJavaIdentifierStart(int codePoint)
可根據 Java 語言規范確定代碼點是否可以啟動標識符。
Character.UnicodeBlock.of(int codePoint)
可搜索代碼點所屬的 Unicode 字符子集。
Character.toUpperCase(int codePoint)
可將給定的代碼點轉換為其大寫等值字符。盡管此方法能夠支持增補字符,但是它仍然不能解決根本的問題,即在某些情況下,逐個字符的轉換無法正確完成。例如,德文字符“"?"”應該轉換為“SS”,這需要使用 String.toUpperCase
方法。
注意大多數接受代碼點的方法并不檢查給定的 int
值是否處于有效的 Unicode 代碼點范圍之內(如上所述,只有 0x0 至 0x10FFFF 之間的范圍是有效的)。在大多數情況下,該值是以確保其有效的方法產生的,在這些低層 API 中反復檢查其有效性可能會對系統性能造成負面的影響。在無法確保有效性的情況下,應用程序必須使用 Character.isValidCodePoint
方法確保代碼點有效。大多數方法對于無效的代碼點采取的行為沒有特別加以指定,不同的實現可能會有所不同。
API 包含許多簡便的方法,這些方法可使用其他低層的 API 實現,但是專家組覺得,這些方法很常用,將它們添加到 J2SE 平臺上很有意義。不過,專家組也排除了一些建議的簡便方法,這給我們提供了一次展示自己實現此類方法能力的機會。例如,專家組經過討論,排除了一種針對 String
類的新構建器(該構建器可以創建一個保持單個代碼點的 String
)。以下是使應用程序使用現有的 API 提供功能的一種簡便方法:
/**
* 創建僅含有指定代碼點的新 String。
*/
String newString(int codePoint) {
return new String(Character.toChars(codePoint));
}
您會注意到,在這個簡單的實現中,toChars
方法始終創建一個中間數列,該數列僅使用一次即立即丟棄。如果該方法在您的性能評估中出現,您可能會希望將其優化為針對最為普通的情況,即該代碼點為 BMP 字符:
/**
* 創建僅含有指定代碼點的新 String。
* 針對 BMP 字符優化的版本。
*/
String newString(int codePoint) {
if (Character.charCount(codePoint) == 1) {
return String.valueOf((char) codePoint);
} else {
return new String(Character.toChars(codePoint));
}
}
或者,如果您需要創建許多個這樣的 string,則可能希望編寫一個重復使用 toChars
方法所使用的數列的通用版本:
/**
* 創建每一個均含有一個指定
* 代碼點的新 String。
* 針對 BMP 字符優化的版本。
*/
String[] newStrings(int[] codePoints) {
String[] result = new String[codePoints.length];
char[] codeUnits = new char[2];
for (int i = 0; i < codePoints.length; i++) {
??? int count = Character.toChars(codePoints[i], codeUnits, 0);
??? result[i] = new String(codeUnits, 0, count);
}
return result;
}
不過,最終您可能會發現,您需要的是一個完全不同的解決方案。新的構建器 String(int codePoint)
實際上建議作為 String.valueOf(char)
的一個基于代碼點的備選方案。在很多情況下,此方法用于消息生成的環境,例如:
System.out.println("Character " + String.valueOf(char) + " is invalid.");
新的格式化 API 支持增補文字,提供一種更加簡單的備選方案:
System.out.printf("Character %c is invalid.%n", codePoint);
使用此高層 API 不僅簡捷,而它有很多特殊的優點:它可以避免串聯(串聯會使消息很難本地化),并將需要移進資源包 (resource bundle) 的字符串數量從兩個減少到一個。
增補字符透視:功能增強
在支持使用增補字符的 Java 2 平臺中的大部分更改沒有反映到新的 API 內。一般預期是,處理字符序列的所有接口將以適合其功能的方式處理增補字符。本部分著重講述為達到此預期所作一些功能增強。
Java 編程語言中的標識符
Java 語言規范指出所有 Unicode 字母和數字均可用于標識符。許多增補字符是字母或數字,因此 Java 語言規范已經參照新的基于代碼點的方法進行更新,以在標識符內定義合法字符。為使用這些新方法,需要檢測標識符的 javac 編譯器和其他工具都進行了修訂。
庫內的增補字符支持
許多 J2SE 庫已經過增強,可以通過現有接口支持增補字符。以下是一些例子:
- 字符串大小寫轉換功能已更新,可以處理增補字符,也可以實現 Unicode 標準中規定的特殊大小寫規則。
java.util.regex
包已更新,這樣模式字符串和目標字符串均可以包含增補字符并將其作為完整單元處理。
- 現在,在
java.text
包內進行整理處理時,會將增補字符看作完整單元。
java.text.Bidi
類已更新,可以處理增補字符和 Unicode 4.0 中新增的其他字符。請注意,Cypriot Syllabary 字符子集內的增補字符具有從右至左的方向性。
- Java 2D API 內的字體渲染和打印技術已經過增強,可以正確渲染和測量包含增補字符的字符串。
- Swing 文本組件實現已更新,可以處理包含增補字符的文本。
字符轉換
只有很少的字符編碼可以表示增補字符。如果是基于 Unicode 的編碼(如 UTF-8 和 UTF-16LE),則舊版的 J2RE 內的字符轉換器已經按照正確處理增補字符的方式實現轉換。對于 J2RE 5.0,可以表示增補字符的其他編碼的轉換器已更新:GB18030、x-EUC-TW(現在實現所有 CNS 11643 層面)和 Big5-HKSCS(現在實現 HKSCS-2001)。
在源文件內表示增補字符
在 Java 編程語言源文件中,如果使用可以直接表示增補字符的字符編碼,則使用增補字符最為方便。UTF-8 是最佳的選擇。在所使用的字符編碼無法直接表示字符的情況下,Java 編程語言提供一種 Unicode 轉義符語法。此語法沒有經過增強,無法直接表示增補字符。而是使用兩個連續的 Unicode 轉義符將其表示為 UTF-16 字符表示法中的兩個編碼單元。例如,字符 U+20000 寫作“\uD840\uDC00”。您也許不愿意探究這些轉義序列的含義;最好是寫入支持所需增補字符的編碼,然后使用一種工具(如 native2ascii)將其轉換為轉義序列。
遺憾的是,由于其編碼問題,屬性文件仍局限于 ISO 8859-1(除非您的應用程序使用新的 XML 格式)。這意味著您始終必須對增補字符使用轉義序列,而且可能要使用不同的編碼進行編寫,然后使用諸如 native2ascii 的工具進行轉換。
經修訂的 UTF-8
Java 平臺對經修訂的 UTF-8 已經很熟悉,但是,問題是應用程序開發人員在可能包含增補字符的文本和 UTF-8 之間進行轉換時需要更加留神。需要特別注意的是,某些 J2SE 接口使用的編碼與 UTF-8 相似但與其并不兼容。以前,此編碼有時被稱為“Java modified UTF-8”(經 Java 修訂的 UTF-8) 或(錯誤地)直接稱為“UTF-8”。對于 J2SE 5.0,其說明文檔正在更新,此編碼將統稱為“modified UTF-8”(經修訂的 UTF-8)。
經修訂的 UTF-8 和標準 UTF-8 之間之所以不兼容,其原因有兩點。其一,經修訂的 UTF-8 將字符 U+0000 表示為雙字節序列 0xC0 0x80,而標準 UTF-8 使用單字節值 0x0。其二,經修訂的 UTF-8 通過對其 UTF-16 表示法的兩個代理代碼單元單獨進行編碼表示增補字符 。每個代理代碼單元由三個字節來表示,共有六個字節。而標準 UTF-8 使用單個四字節序列表示整個字符。
Java 虛擬機及其附帶的接口(如 Java 本機接口、多種工具接口或 Java 類文件)在 java.io.DataInput
和 DataOutput
接口和類中使用經修訂的 UTF-8 實現或使用這些接口和類 ,并進行序列化。Java 本機接口提供與經修訂的 UTF-8 之間進行轉換的例程。而標準 UTF-8 由 String
類、java.io.InputStreamReader
和 OutputStreamWriter
類、java.nio.charset
設施 (facility) 以及許多其上層的 API 提供支持。
由于經修訂的 UTF-8 與標準的 UTF-8 不兼容,因此切勿同時使用這兩種版本的編碼。經修訂的 UTF-8 只能與上述的 Java 接口配合使用。在任何其他情況下,尤其對于可能來自非基于 Java 平臺的軟件的或可能通過其編譯的數據流,必須使用標準的 UTF-8。需要使用標準的 UTF-8 時,則不能使用 Java 本機接口例程與經修訂的 UTF-8 進行轉換。
在應用程序內支持增補字符
現在,對大多數讀者來說最為重要的問題是:必須對應用程序進行哪些更改才能支持增補字符?
答案取決于在應用程序中進行哪種類型的文本處理和使用哪些 Java 平臺 API。
對于僅以各種形式 char
序列([char[]
、java.lang.CharSequence
實現、java.text.CharacterIterator
實現)處理文本和僅使用接受和退回序列(如 char
序列)的 Java API 的應用程序,可能根本不需要進行任何更改。Java 平臺 API 的實現應該能夠處理增補字符。
對于本身解釋單個字符、將單個字符傳送給 Java 平臺 API 或調用能夠返回單個字符的方法的應用程序,則需要考慮這些字符的有效值。在很多情況下,往往不要求支持增補字符。例如,如果某應用程序搜索 char
序列中的 HTML 標記,并逐一檢查每個 char
,它會知道這些標記僅使用 Basic Latin 字符子集中的字符。如果所搜索的文本含有增補字符,則這些字符不會與標記字符混淆,因為 UTF-16 使用代碼單元表示增補字符,而代碼單元的值不會用于 BMP 字符。
只有在某應用程序本身解釋單個字符、將單個字符傳送給 Java 平臺 API 或調用能夠返回單個字符的方法且這些字符可能為增補字符時,才必須更改該應用程序。在提供使用 char
序列的并行 API 時,最好轉而使用此類 API。在其他情況下,有必要使用新的 API 在 char
和基于代碼點的表示法之間進行轉換,并調用基于代碼點的 API。當然,如果您發現在 J2SE 5.0 中有更新、更方便的 API,使您能夠支持增補字符并同時簡化代碼(如上 格式化范例 中所述),則沒有必要這樣做。
您可能會猶豫,是將所有文本轉換為代碼點表示法(即 int[]
)然后在該表示法中處理,還是在大多數情況下仍采用 char
序列,僅在需要時轉換為代碼點,兩者之間孰優孰劣很難確定。當然,總體來說,Java 平臺 API 相對于 char
序列肯定具有一定的優勢,而且采用 Java 平臺 API 可以節省內存空間。
對于需要與 UTF-8 之間進行轉換的應用程序,還需要認真考慮是需要標準的 UTF-8 還是經修訂的 UTF-8,并針對每種 UTF-8 采用適當的 Java 平臺。“經修訂的 UTF-8”部分介紹進行正確選擇所需的信息。
使用增補字符測試應用程序
經過前面部分的介紹后,無論您是否需要修訂應用程序,測試應用程序是否運行正常始終是一種正確的做法。對于不含有圖形用戶界面的應用程序,有關“在源文件內表示增補字符” 的信息有助于設計測試用例。以下是有關使用圖形用戶界面進行測試的補充信息。
對于文本輸入,Java 2 SDK 提供用于接受“\Uxxxxxx”格式字符串的代碼點輸入方法,這里大寫的“U”表示轉義序列包含六個十六進制數字,因此允許使用增補字符。小寫的“u”表示轉義序列“\uxxxx”的原始格式。您可以在 J2SDK 目錄 demo/jfc/CodePointIM 內找到此輸入方法及其說明文檔。
對于字體渲染,您需要至少能夠渲染一些增補字符的字體。其中一種此類字體為 James Kass 的 Code2001 字體,它提供手寫體字形(如 Deseret 和 Old Italic)。利用 Java 2D 庫中提供新功能,您只需將該字體安裝到 J2RE 的 lib/fonts/fallback 目錄內即可,然后它可自動添加至在 2D 和 XAWT 渲染時使用的所有邏輯字體 — 無需編輯字體配置文件。
至此,您就可以確認,您的應用程序能夠完全支持增補字符了!
結論
對增補字符的支持已經引入 Java 平臺,大部分應用程序無需更改代碼即可處理這些字符。解釋單個字符的應用程序可以在 Character
類和多種 CharSequence
子類中使用基于代碼點的新 API。
鳴謝
Java 平臺中的增補字符支持由 Java Community Process 的 JSR-204 專家組設計。技術規范設計主持為 Masayoshi Okutsu 和 Brian Beck (Sun Microsystems),其他專家組成員有 Craig Cummings (Oracle)、Mark Davis (IBM)、Markus Eble (SAP AG)、Jere K?pyaho (Nokia Corp.)、Kazuhiro Kazama (NTT)、Kenji Kazumura (Fujitsu Limited)、Eiichi Kimura (NEC Corp.)、Changshin Lee (Tmax Soft Inc.) 和 Toshiki Murata (Oki Electric Industry Co.)。參考實現由 Sun Microsystems 的 Java Internationalization 團隊完成,并承蒙位于圣何塞的 IBM Globalization Center of Competency 的協助。技術規范的技術兼容套件為 Java Compatibility Kit,由 Sun Microsystems 的 JCK 團隊實現。
參考書目
Masayoshi Okutsu, Brian Beck (ed.): Unicode Supplementary Character Support. Proposed Final Draft. Sun Microsystems, 2004.
Java 2 Platform Standard Edition 5.0 API Specification. Sun Microsystems, 2004.
The Unicode Consortium: The Unicode Standard, Version 4.0. Addison-Wesley, 2003.
Ken Whistler, Mark Davis: Character Encoding Model. Unicode Technical Report #17. The Unicode Consortium, 2000.
James Kass: Code2001, a Plane 1 Unicode-based Font.
關于作者
Norbert Lindenberg 是 Sun Microsystems 的 Java Web Services 團隊內 Java Internationalization 技術主管。在加盟 Sun 之前,曾經供職于 General Magic 和 Apple Computer,參與過多個國際化項目。他畢業于德國的卡爾斯魯厄大學,擁有計算機科學理科碩士學位。
Masayoshi Okutsu 是 Sun Microsystems 的 Java Web Services 團隊的一名國際化工程師,目前擔任 Unicode Supplementary Character Support 的 Java Specification Request 204 的技術規范主管。在加盟 Sun Microsystems 之前,供職于 Digital Equipment Corporation,期間曾經參與多個國際化項目。他畢業于日本山形大學,擁有電子工程理學士學位。
1 本網站中使用的術語“Java 虛擬機”或“JVM”是指針對 Java 平臺的虛擬機。