2012-12-19 76 views
6

我正在学习Java。我发现表达式经常必须被转换成某种类型才能正确执行。例如,算术评估中,字节都提升到整数,所以下面的表达式将抛出一个错误:在Java中铸造字符

byte b = 10; 
int i; 
i = b*b; //ok, assigning an integer evaluation to an integer variable 
b = b*b; // throws error, coz assigning integer evaluation to byte variable 

现在,我知道,分配给一个字符变量的整数都很好:char a; a = 88;是好的。但是,如果我这样做:

char c2 = 'b', c3 = 'c'; 
c2 = c2 + c3; //throws error 
c2 = (char)(c2 + c3); //works fine 

为什么它抛出一个错误,当不是铸造?毕竟,右侧仍然是一个整数,因此将一个整数赋值给一个字符变量应该工作得很好。

+0

'88'是一个字节,不只是一个整数 –

回答

6

c2 + c3中,两个操作数都被隐含地加宽为int,所以加法的结果也是int

JLS §15.18.2. Additive Operators (+ and -) for Numeric Types

Binary numeric promotion is performed on the operands (§5.6.2).

JLS §5.6.2. Binary Numeric Promotion

When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:

Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

  • If either operand is of type double, the other is converted to double.

  • Otherwise, if either operand is of type float, the other is converted to float.

  • Otherwise, if either operand is of type long, the other is converted to long.

  • Otherwise, both operands are converted to type int.

你因此最终获得的int。将其分配给char变量需要进行明确的转换。

你说:

Since integer value can be assigned to a character variable...

只有不断整数表达式可以不进行强制转换分配给char变量。

JLS §5.2. Assignment Conversion

In addition, if the expression is a constant expression (§15.28) of type byte, short, char, or int:

  • A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.

这种自动收缩转换,在这里并不适用。你需要明确的演员。

+0

是的,这就是我所说的。右侧的字符被提升为整数,从而将整数结果赋给左侧的变量。由于整数值可以分配给一个字符变量,为什么它会抛出一个错误? – SexyBeast

+0

+1为不变的东西 - 我找不到参考;-) – assylias

+0

@Cupidvogel:这是不正确的。只有*常量*整数表达式自动缩小,这里我们没有看到一个。我已经扩大了答案。 – NPE

3

将int分配给char不一定正常。字符只有16位,整数是32位,所以可能会出现溢出。

一般来说,如果分配结果不会发生溢出,Java只允许分配基本值而不需要强制转换。

+0

这里为什么会出现溢出? – SexyBeast

+0

简单:取两个最高可能的char值并添加它们。这是一个溢出。 '('\ uFFFF'+'\ uFFFF')> Character.MAX_VALUE' –

+0

这是一个快捷方式。 'int i = 1; char c = i;'虽然没有溢出,但不会编译。 – assylias

0

因为编译器可以确定该值,所以将一个int 88赋值给char。

编译器无法处理c2 = c2 + c3的情况。值c2 + c3必须在运行时进行评估。因此,编译器无法确定必须分配的实际char值。

1
char c2 = 'b', c3 = 'c'; 
c2 = c2 + c3; //throws error 
c2 = (char)(c2 + c3); //works fine 

,当你做这些字符的c2+ c3

ASCII值增加而得到返回结果int。 当您将int结果分配给char时,会发生错误。

+0

这就是我说的,如果我做'char c = 99;'它不会抛出错误,为什么在这里呢? – SexyBeast

+0

char c = 99; 99被隐式转换为char。由于在编译器时间已知数据类型为99,但字符算术返回类型结果在编译时未知。 –

0

char是2个字节,int是4个字节。当你写char c = 1;这并不意味着1是int,它只是一个常量,而javac知道1适合char。但是c2 = c2 + c3;是算术运算,javac会将其解释为(int)c2 + (int)c3,并产生int结果。 int不适合char,所以javac会警告您可能会丢失精度。

+0

** char是2个字节,int是4个字节。当你写char c = 1;它并不意味着1是int,它只是一个用于javac的常量,并且javac知道1适合char。**当1占用4个字节和char 2个字节时,如何才能使用'char'? – SexyBeast

+0

其实1只占用1个字节,它是0x1,编译器知道它适合。但是如果你有int i = 1; char c = i;它不会编译,因为我是一个var它可以超过2个字节 –

+0

所以你说,即使整数有一个默认的空间占用率,整数文字不遵守,并占用空间特设? – SexyBeast

0

看一看螺纹:

Integer arithmetic in Java with char and integer literal

的原因似乎是, “C2 = C2 + C3;”不能由编译器检查(它在运行时执行),而“char a; a = 88;”由编译器直接完成。

+0

为什么会这样?作业之间有什么区别? – SexyBeast

+0

这是在这里解释:http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.2 – izaera

+0

它只是这样工作:如果编译器可以将一个数值在飞到字节或字符它做到了。如果分配在运行时执行,则遵循其他转换路径。把它作为一个方便的编译器工具或作为语言中的不连贯性(无论你最喜欢什么;-) – izaera

0

进一步澄清的一个例子:

char c1 = Character.MAX_VALUE; 
char c2 = Character.MAX_VALUE; 
char c3 = (char) (c1 + c2); 
int i3 = c1 + c2; 

System.out.printf("After casting to char: %s, the int value: %s%n", (int) c3, i3); 

因此,与铸造,我们实际上有一个错误的数学结果。

0

对于每个基本类型可以容纳多少值有一定限制java.Assigning算术运算的结果可能会在运行时产生不可预知的结果,JVM不确定char是否可以容纳,因此编译错误。