我正在尝试从char
值>获得int
0xFFFF
。但相反,我总是得到相同的char
值,当投放到int
时,会打印值65535
(0xFFFF
)。
我无法理解为什么它会为unicode生成符号> 0xFFFF
。
int hex = 0x10FFFF;
char c = (char)hex;
System.out.println((int)c);
我预计输出为0x10FFFF
。相反,输出返回65535
。
答案 0 :(得分:3)
这是因为,int
是4个字节,char
只有2个字节。因此,您无法在char
中代表int
中的所有值。使用标准无符号整数表示,您只能在2字节值中表示从0
到2^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