Java 字符与具有两个代码单元的字符一起使用

摘自《Core Java》,第 1 卷,第 9 版,第 69 页:

字符 Z 在 UTF-16 编码中需要两个代码单元。叫

String sentence = "ℤ is the set of integers"; // for clarity; not in book
char ch = sentence.charAt(1)

不返回空格,而是返回 Z 的第二个代码单元。

但似乎确实返回了一个空格。例如,以下代码中的语句的计算结果为 。sentence.charAt(1)iftrue

String sentence = "ℤ is the set of integers";
if (sentence.charAt(1) == ' ')
    System.out.println("sentence.charAt(1) returns a space");

为什么?

我在Ubuntu 12.10上使用JDK SE 1.7.0_09,如果相关的话。


答案 1

这听起来像是说“Z”在基本的多语言平面中不是UTF-16字符,但实际上它是。

Java 将 UTF-16 与代理项对一起使用,以表示不在基本多语言平面中的字符。由于“Z”(0x2124)位于基本的多语言平面中,因此它由单个代码单元表示。在您的示例中,将返回“Z”,并将返回“ ”。sentence.charAt(0)sentence.charAt(1)

由代理项对表示的字符具有两个代码单元组成该字符。 将返回第一个代码单元,并返回第二个代码单元。sentence.charAt(0)sentence.charAt(1)

请参阅 http://docs.oracle.com/javase/6/docs/api/java/lang/String.html

字符串表示 UTF-16 格式的字符串,其中增补字符由代理项对表示(有关详细信息,请参阅字符类中的 Unicode 字符表示部分)。索引值引用字符代码单位,因此增补字符使用字符串中的两个位置。


答案 2

根据文档,String在内部表示为utf-16,因此为您提供了两个码位。如果您有兴趣查看各个代码点,则可以使用此代码(来自以下答案):charAt()

final int length = sentence.length();
for (int offset = 0; offset < length; ) {
   final int codepoint = sentence.codePointAt(offset);

   // do something with the codepoint

   offset += Character.charCount(codepoint);
}

推荐