Java中的原始强制转换和赋值

时间:2013-06-14 14:32:57

标签: java

我理解为什么以下是错误的:

byte a = 3; 
byte b = 8; 
byte c = a + b;  // compile error

它不会编译。表达式始终会生成int。所以我们应该做了明确的演员:

byte c = (byte) (a + b);   // valid code

但是我不明白为什么以下是正确的

byte d = 3 + 8;   // it's valid! why?

因为字面整数(例如3或8)总是隐含int。而且int-or-smaller表达式也总是导致int。谁能解释一下这里发生了什么?

我唯一可以猜到的是编译器将此表达式等同于以下内容:

byte d = 11;

并不认为这是一个表达。

3 个答案:

答案 0 :(得分:46)

less†3 + 8是否在编译时评估为11更多更多有关在某些情况下,明确允许编译器隐式地将int缩小为byte s。特别是,语言规范明确允许将byte类型int的常量表达式隐式缩小转换,以便在编译时适合byte

JLS here is section §5.2:

的相关部分
  

此外,如果表达式是类型byteshort的常量表达式(第15.28节),   charint

     
      
  • 如果类型为,则可以使用缩小的基元转换   变量是byteshortchar和常量的值   表达式可以在变量的类型中表示
  •   
     

编译时缩小常量意味着代码如下:   byte theAnswer = 42;   被允许。没有缩小,整数文字42具有类型int的事实   意味着需要投射到byte

†:显然,根据规范,需要评估常量表达式以确定它是否适合较窄的类型。 但重点是,如果没有规范的这一部分,编译器将不允许进行隐式缩小转换

我们在这里说清楚:

byte a = 3; 
byte b = 8; 

允许这些的原因是由于规范的上述部分。也就是说,允许编译器将文字3隐式缩小转换为byte。这不是因为编译器在编译时将常量表达式3计算为其值3

答案 1 :(得分:41)

  

我唯一可以猜到的是编译器将此表达式等同于以下内容:

是的。只要右侧表达式由常量(符合所需的基本类型 - 请参阅@Jason关于JLS对此的说明的答案),您就可以做到这一点。这将无法编译,因为128超出范围:

byte a = 128;

请注意,如果您将第一个代码段转换为:

final byte a = 3; 
final byte b = 8; 
byte c = a + b;

它编译!由于你的两个字节是final ,它们的表达式是常量,这次,编译器可以确定结果在首次初始化时适合一个字节。

然而,这不会编译:

final byte a = 127; // Byte.MAX_VALUE
final byte b = 1;
byte c = a + b // Nope...

编译器会因“可能的精度损失”而出错。

答案 2 :(得分:0)

这是因为38编译时常量。

因此,在编译时,编译器可以识别出3 + 8可以放入byte变量。

如果您将ab设为最终(常量)变量。 a + b将成为编译时常量。因此,它将编译没有任何问题。

    final byte a = 3;
    final byte b = 8;
    byte c = a + b;