添加字节时的不同编译器行为

时间:2011-10-06 22:27:51

标签: java

byte b1 = 3;
byte b2 = 0;

b2 = (byte) (b2 + b1);  // line 3
System.out.println(b2);

b2 = 0;
b2 += b1;               // line 6
System.out.println(b2);

在第3行,如果我们不将结果类型转换为字节,那么这是一个编译错误 - 这可能是因为加法的结果总是int而int不适合一个字节。但显然我们不必在第6行进行类型转换。这两个语句,第3行和第6行都不等同吗?如果不是那么还有什么不同?

2 个答案:

答案 0 :(得分:10)

是的,这两行是等价的 - 但是它们使用了语言的不同部分,并且它们被JLS的不同部分所覆盖。第3行是普通+运算符,应用于已提升为int的字节,给出int结果。必须先将其转换为可以将其分配回byte变量。

第6行是section 15.26.2 of the JLS

中描述的复合赋值运算符
  

在运行时,表达式以两种方式之一进行评估。如果左侧操作数表达式不是数组访问表达式,则需要四个步骤:

     
      
  • 首先,评估左侧操作数以产生变量。如果此评估突然完成,则赋值表达式出于同样的原因突然完成;不评估右侧操作数,也不进行任何分配。
  •   
  • 否则,保存左侧操作数的值,然后评估右侧操作数。如果此评估突然完成,则赋值表达式会因同样的原因而突然完成,并且不会发生任何分配。
  •   
  • 否则,左侧变量的保存值和右侧操作数的值用于执行复合赋值运算符指示的二元运算。如果此操作突然完成,则赋值表达式会因同样的原因突然完成,并且不会发生任何分配。
  •   
  • 否则,将二进制运算的结果转换为左侧变量的类型,将值集转换(第5.113节)转换为相应的标准值集(不是扩展指数值集),转换结果存储在变量中。
  •   

这是使其与众不同的最后一部分(如突出显示)。

事实上,该部分的开头显示了等价:

  

E1 op = E2 形式的复合赋值表达式等效于 E1 =(T)((E1)op(E2)),其中 T E1 的类型,但 E1 仅评估一次。

答案 1 :(得分:-2)

Java在涉及整数类型的操作和转换上弄得一团糟。最好的建议是,尽可能使用int。避免使用byte/short/char,在进行任何计算之前将其显式转换为int