将 int 转换为 char 然后再转换回 int - 并不总是给出相同的结果

Converting a int to char and then back to int - doesn't give same result always

我正在尝试从 int 值 > 0xFFFF 中获取 char。但相反,我总是得到相同的 char 值,当转换为 int 时,打印值 65535 (0xFFFF).

我不明白为什么它会为 unicode > 0xFFFF.

生成符号
int hex = 0x10FFFF;
char c = (char)hex;
System.out.println((int)c);

我预计输出为 0x10FFFF。相反,输出返回为 65535.

这是因为,int 是 4 个字节,而 char 只有 2 个字节。因此,您不能像在 int 中那样在 char 中表示所有值。使用标准的无符号整数表示,您只能用 2 字节值表示从 02^16 - 1 == 65535 的值范围,因此如果您将该范围外的任何数字转换为 2 字节值并且回来,你会丢失数据。

int 是 4 个字节。 char 是 2 个字节。 您的号码完全在 int 可以容纳的范围内,但不是 which char 可以容纳的范围。 因此,当您将该数字转换为 char 时,它会丢失数据并成为 char 可以容纳的最大值,这就是它打印的内容,即 65535

您的数字太大,不能是 2 个字节的字符。但它足够小,适合作为 4 个字节的 int。 65535 是适合 char 的最大数量,因此这就是您获得该值的原因。此外,如果 char 足够大以适合您的数字,当您将它返回到 int 时,它可能返回 0x10FFFF 的十进制值,即 1114111.

不幸的是,我认为您期望 Java char 与 Unicode 代码点相同。它们不是一回事。

Javachar,其他答案已经表示,只能支持16位可以表示的码位,而Unicode需要21位才能支持所有码位。

换句话说,Java char 本身只支持基本多语言平面字符(代码点 <= 0xFFFF)。在 Java 中,如果你想表示一个扩展平面中的 Unicode 代码点(代码点 > 0xFFFF),那么你需要代理字符或一对字符来做到这一点。这就是 UTF-16 的工作原理。而且,在内部,这也是 Java 字符串的工作方式。只是为了好玩,运行 下面的代码片段可以看到如果代码点是 > 0xFFFF:

,单个 Unicode 代码点实际上是如何由 2 个字符表示的
// Printing string length for a string with 
// a single unicode code point: 0x22BED.
System.out.println("".length()); // prints 2, because it uses a surrogate pair.

如果您想安全地将表示 Unicode 代码点的 int 值转换为 char(或更准确地说是 chars),然后再将其转换回来到 int 代码点,您将必须使用这样的代码:

public static void main(String[] args) {
    int hex = 0x10FFFF;
    System.out.println(Character.isSupplementaryCodePoint(hex)); // prints true because hex > 0xFFFF
    char[] surrogateChars = Character.toChars(hex);
    int codePointConvertedBack = Character.codePointAt(surrogateChars, 0);
    System.out.println(codePointConvertedBack); // prints 1114111
}

或者,您可以使用 String,而不是操作 char 数组,如下所示:

public static void main(String[] args) {
    int hex = 0x10FFFF;
    System.out.println(Character.isSupplementaryCodePoint(hex)); // prints true because hex > 0xFFFF
    String s = new String(new int[] {hex}, 0, 1);
    int codePointConvertedBack = s.codePointAt(0);
    System.out.println(codePointConvertedBack); // prints 1114111
}

进一步阅读:Java Character Class