Java 平臺中的增補字符

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 代碼單元
00000041
000000DF
00006771
00010400
UTF-16 代碼單元
0041
00DF
6771
D801 DC00
UTF-8 代碼單元
41
C3 9F
E6 9D B1
F0 90 90 80

另外,本文在許多地方使用術語字符序列或 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)。StringStringBuffer 接受並行 API,並將它們解釋爲 UTF-16 序列或 UTF-32 序列;其他 char 序列繼續基於 UTF-16。
  • 使用 int 表示增補的代碼點。StringStringBuffer 接受並行 API,並將它們解釋爲 UTF-16 序列或 UTF-32 序列;其他 char 序列繼續基於 UTF-16。
  • 使用代理 char 對,表示增補代碼點。所有形式的 char 序列基於 UTF-16。
  • 引入一種封裝字符的類。StringStringBuffer 接受新的 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) 是兩種典型的例子。在將代碼點插入字符序列時,大多數情況下均有一些針對 StringBufferStringBuilder 類的 appendCodePoint(int codePoint) 方法,以及一個用於提取表示代碼點的 int[]String 構建器。

幾種用於分析代碼單元和代碼點的方法有助於轉換過程:Character 類中的 isHighSurrogateisLowSurrogate 方法可以識別用於表示增補字符的 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.DataInputDataOutput 接口和類中使用經修訂的 UTF-8 實現或使用這些接口和類 ,並進行序列化。Java 本機接口提供與經修訂的 UTF-8 之間進行轉換的例程。而標準 UTF-8 由 String 類、java.io.InputStreamReaderOutputStreamWriter 類、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.): UnicodeSupplementary Character Support. Proposed Final Draft. Sun Microsystems, 2004.

Java2 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 平臺的虛擬機。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章