【问题标题】:Converting a int to char and then back to int - doesn't give same result always将 int 转换为 char 然后再转换回 int - 并不总是给出相同的结果
【发布时间】:2015-09-14 15:40:21
【问题描述】:

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

我不明白为什么它会为 unicode > 0xFFFF 生成符号。

int hex = 0x10FFFF;
char c = (char)hex;
System.out.println((int)c);

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

【问题讨论】:

  • 您期待什么?你知道intchar 之间的区别吗?
  • 是的,我知道其中的区别,但我正在尝试生成一个 UTF8 编码为我提供 4 个字节的字符,但我没能做到。

标签: java unicode char int


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        正如其他答案已经表达的那样,Java char 只能支持可以用 16 位表示的代码点,而 Unicode 需要 21 位才能支持所有代码点。

        换句话说,Java char 本身仅支持基本多语言平面字符(代码点 0xFFFF)。在 Java 中,如果您想表示位于其中一个扩展平面中的 Unicode 代码点(代码点 > 0xFFFF),那么您需要代理字符或一对字符来执行此操作。这就是UTF-16 的工作原理。而且,在内部,这也是 Java 字符串的工作方式。只是为了好玩,运行以下 sn -p 来查看单个 Unicode 代码点实际上是如何用 2 个字符表示的,如果代码点 >0xFFFF

        // 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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-03-18
          • 2013-09-10
          • 2020-12-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-03
          相关资源
          最近更新 更多