17

来自核心 Java,第一卷。1,第 9 版,第 69:

字符 ℤ 在 UTF-16 编码中需要两个代码单元。打电话

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

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

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

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。

4

4 回答 4

10

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

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

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

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

String 表示 UTF-16 格式的字符串,其中补充字符由代理对表示(有关更多信息,请参见 Character 类中的 Unicode Character Representations 部分)。索引值指的是字符代码单元,因此补充字符使用字符串中的两个位置。

于 2013-01-04T04:46:20.917 回答
8

根据文档,字符串在内部表示为 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);
}
于 2013-01-04T03:12:51.177 回答
3

Horstmann 正在谈论需要两个 UTF-16 代码单元的“Z”。看看这段代码:

public class Main {
    public static void main(String[] args)
    {
        String a = "\uD83D\uDE02 is String";
        System.out.println("Length: " + a.length());
        System.out.println(a.charAt(0));
        System.out.println(a.charAt(1));
        System.out.println(a.charAt(2));
        System.out.println(a.charAt(3));
    }
}

在 IntelliJ Idea 中,我什至无法将 4 字节字符粘贴为一个字符,因为在粘贴此表情符号时:IDE 会自动将其转换为:“\uD83D\uDE02”。请注意,此表情符号计为 2 个字符。

如果要计算“实际长度”,则应使用: System.out.println("Real length: " + a.codePointCount(0, a.length()));

看看:实际使用中最常见的非BMP Unicode字符有哪些?

于 2019-01-26T21:40:26.463 回答
2

Javadocs对此进行了解释:

String 表示 UTF-16 格式的字符串,其中补充字符由代理对表示(有关更多信息,请参见 Character 类中的 Unicode Character Representations 部分)。索引值指的是字符代码单元,因此补充字符使用字符串中的两个位置。

简而言之,这本书是错误的。

编辑从下面的评论中添加:昨晚我没有想到的是,您在问题中使用的角色实际上并不是他们正在谈论的角色,而他们真正想要的是当您拥有有一个需要四个字节而不是两个字节的字符。Javadoc 中的上述段落链接到另一个 javadoc;Unicode Character Representations讨论了这一点的后果。

于 2013-01-04T03:12:30.517 回答