2010-09-09 47 views
16

有人可以向我解释为什么下面的代码在Java中编译好吗?用char和整数字面值在Java中的整数算术

char c = 'a' + 10; 

为什么这不等于下面的,它不会编译?

int i = 10; 
char c = 'a' + i; 

Java语言规范(第3.10.1节)指出“字面一个整数是long类型的,如果它是与ASCII字母L或l(ELL)后缀;否则,它是int类型(§4.2的0.1)。”第4.2.2节提到“数字运算符,其结果为intlong类型的值。”所以根据我的理解,添加的结果应该是int,它不能被分配给char变量c

但是,它编译得很好(至少在Sun JDK 1.6.0 release 17和Eclipse Helios中)。

也许是一个人为的例子,但它被用在我一直在教的Java入门课程中,现在我发现我不明白它为什么起作用。

+3

感谢所有回答。对于任何感兴趣的人来说,语言规范(赋值转换)的第5.2节实际上都会说“另外,如果表达式是byte类型的short表达式(第15.28节),则为short,char或int:...缩小原语转换如果变量的类型是byte,short或char,并且常量表达式的值可以用变量的类型表示,则可以使用它。“ – Ben 2010-09-10 09:09:40

+1

如果你像我一样碰巧遇到了这个问题,因为你想知道如何将索引字符转换为字符串,在这里你可以去;当'i = 2'时,String.valueOf((char)('a'+ i))'返回字符串“c”。 – JohnnyLambada 2013-10-23 23:01:11

回答

9

'a' + 10编译时间常量表达式'k'的值,它可以初始化char类型的变量。这与在[-128,127]中能够使用文字整数指定byte变量相同。在[128,255]范围内的byte可能更令人讨厌。

+0

谢谢。查找*编译时常量表达式*将我引向语言规范的相关部分。 – Ben 2010-09-10 09:12:59

13

这是因为编译器可以检查它('a' + 10)是否在char的范围内,而不能(通常)检查'a' + <an integer>是否在范围内。

+0

char c = 65535;编译,但不是char c = 65536; – einarmagnus 2010-09-09 21:21:41

+0

字符是两个字节,所以这是有道理的。 – einarmagnus 2010-09-09 21:23:52

+0

'char c = 103000;'不。 UCS-2 ftw! – 2010-09-09 21:24:43

1

该常数是一个不同的类型(我知道规范说10应该是一个int,但编译器不会这样看)。

char c = 'a' + 10,10实际上被认为是一个char类型的常量变量(所以它可以被添加到a中)。因此char c = char + char的作品。

int i = 10; char c = 'a' + i;要添加炭为整数(一个整数可以比一个char大得多,所以它选择更大的数据类型[int]是结果a.k.a:'a' + i = int + int)。所以加法的结果是一个整数,它不适合char c

如果你明确铸造i是一个字符(例如:char c = 'a' + (char)i;)它可以工作,或者如果你做了相反的(例如:int c = (int)'a' + i;),它会工作。

+0

我认为说10被认为是char类型是不正确的。相反,正如Tom Hawtin所说的,表达式'a'+ 10'是*编译时常量*,因此编译器可以进行缩小转换。实际上,'char c ='a'+(char)i;'不起作用,因为右侧是int类型,不是编译时常量。 – Ben 2010-09-10 09:17:02

3

char实际上是一个范围为0-65535的无符号16位整数。因此,您可以将该范围内的任何整数字面量赋值给一个字符,例如“char c = 96”,从而导致“c”保持字符“a”。您可以使用System.out.println(c)打印结果。

对于“char c ='a'+ 10”右侧的常量表达式,由于Java数字提升规则而将a提升为int,整数值为96.之后加10后,我们得到一个文字整数106,它可以被分配给一个字符。“char c ='a'+ i”的右侧不是常量表达式,表达式结果分配规则需要从int到char的显式转换,即“char c =(char) ('a'+ i)“。