从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
时,情况并非如此?
好的,那里有几个截然不同的问题。
我认为第一个问题是:
你为什么看到? 当你输出ch2
和ch3
因为您输出的是无效字符。 Java字符代表UTF-16代码点 ,而不是实际字符。 UTF-16中的某些Unicode字符需要两个 Java char
才能存储。 有关UTF-16的更多信息,请参见Unicode常见问题解答 。 在UTF-16中,值0xFFFF
(这是ch2
和ch3
包含的值)作为独立值无效; 即使它是,也没有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。 语言因设计妥协而有所不同。
我会提交,如果你做正确的事情 – 正确的方式 – 使用char
或Character
或String
,你就不会遇到这样的问题。 忘记“ASCII仍然像往常一样从0到127,以及扩展的8位字符集,ISO-Latin-1。” Java使用Unicode; 接受它。