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

时间:2015-06-27 22:44:39

标签: java unicode char int

我正在尝试从char值>获得int 0xFFFF。但相反,我总是得到相同的char值,当投放到int时,会打印值655350xFFFF)。

我无法理解为什么它会为unicode生成符号> 0xFFFF

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

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

4 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

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

答案 2 :(得分:2)

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

答案 3 :(得分:2)

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

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

换句话说,Java char本身只支持Basic Multilingual Plane字符(代码点< = 0xFFFF)。在Java中,如果要表示其中一个扩展平面(代码点> 0xFFFF)中的Unicode代码点,则需要使用代理字符或一对字符来执行此操作。这就是UTF-16的工作原理。而且,在内部,这也是Java字符串的工作方式。只是为了好玩,运行以下代码段,看看如果代码点是>,单个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(或更准确地说是char),然后将其转换回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
}

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

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