从int到char和ASCII值的类型转换

int a1 = 65535; char ch2 = (char) a1; System.out.println("ASCII value corresponding to 65535 after being typecasted : "+ch2);// prints? char ch3 = 65535; System.out.println("ASCII value corresponding to 65535 : "+ch3);// again prints? 

我引用Herbert Schildt的第3章:数据类型,变量和数组:

char的范围是0到65535.没有负的字符。 称为ASCII的标准字符集一如既往地保持在0到127之间,扩展的8位字符集ISO-Latin-1的范围从0到255.由于Java旨在允许程序在全球范围内编写使用,它会使用Unicode来表示字符。 只要在范围内,也可以将整数赋给char。

 //char ch33 = 65536; compilation-error, ofcourse since out of char range (which is 0 - 65535) int a11 = 65536; char ch22 = (char) a11; System.out.println("ASCII value corresponding to 65536 after being typecasted : "+ch22); // non-printing character(appearance of a small square like figure in eclipse console) 

问题是:为什么这行没有编译错误: char ch22 = (char) a11 ,即使char ch33 = 65536不起作用? 还有一件事,当采用int a1 = 65535时,情况并非如此?

好的,那里有几个截然不同的问题。

我认为第一个问题是:

你为什么看到? 当你输出ch2ch3

因为您输出的是无效字符。 Java字符代表UTF-16代码点 ,而不是实际字符。 UTF-16中的某些Unicode字符需要两个 Java char才能存储。 有关UTF-16的更多信息,请参见Unicode常见问题解答 。 在UTF-16中,值0xFFFF (这是ch2ch3包含的值)作为独立值无效; 即使它是,也没有Unicode U + FFFF字符 。

重新输出ch22 :你看到一个小盒子的原因是你输出了字符0(char)65536的结果为0 ,见下文),这是一个“控制字符”(下面的所有字符) 32 – 正常空格字符 – 是各种控制字符)。 字符0是“空”字符,对于该字符,我没有普遍接受的字形。

为什么在执行int a11 = 65536; char ch22 = (char) a11;时没有错误int a11 = 65536; char ch22 = (char) a11; int a11 = 65536; char ch22 = (char) a11;

因为这就是Java 缩小原始转换的定义方式。 没有错误; 相反,只使用相关位:

将有符号整数缩小到整数类型T只会丢弃除n个最低位之外的所有位,其中n是用于表示类型T的位数。除了可能丢失有关数值大小的信息之外,这可能导致结果值的符号与输入值的符号不同。

关于为什么char ch22 = (char) a11有效

来自java规范

缩小的原始转换可能丢失关于数值的总量值的信息,并且还可能失去精度和范围。

[…]

将有符号整数缩小到整数类型T只会丢弃除n个最低位之外的所有位,其中n是用于表示类型T的位数。除了可能丢失有关数值大小的信息之外,这可能导致结果值的符号与输入值的符号不同。


关于为什么char c = 65536不起作用

来自java规范

如果变量的类型是:则可以使用缩小的基元转换,然后进行装箱转换:

  • 字节和常量表达式的值可在类型字节中表示。
  • Short和常量表达式的值可以在short类型中表示。
  • 字符和常量表达式的值可在char类型中表示。

65536本身并不是char值

例如

  • 1同时是byte,short,char,int和long值。
  • 256是short,char,int和long值,但不是字节值。
  • 65535是char,int和long值,但既不是字节也不是short值。
  • -1是byte,short,int,long值,但不是char值。
  • 65536只是一个int和long值。

char c = (char)65536; 将工作

Java的char类型包含Unicode / UTF-16代码单元,其中一个或两个代码点编码。 并非所有16位正整数都是有效的代码单元。 而且,由于您希望处理char而不是String ,因此您需要将值限制为仅使用一个代码单元编码的代码点。

65535不是有效的UTF-16代码单元,也不是有效的Unicode代码点。

至于你的问题,为什么你没有得到exception,我只能与其他类似整数的操作进行比较,在这些操作中你没有溢出和类似的exception结果的exception。 语言因设计妥协而有所不同。

我会提交,如果你做正确的事情 – 正确的方式 – 使用charCharacterString ,你就不会遇到这样的问题。 忘记“ASCII仍然像往常一样从0到127,以及扩展的8位字符集,ISO-Latin-1。” Java使用Unicode; 接受它。