使用字节数据类型时JAVA的精度损失

时间:2014-07-15 17:47:47

标签: java

byte b=9 ;
b=b+6 ;

给出编译错误(可能会导致精度损失) 为什么b=9没有给出错误,而b=b+9给出精度损失?

我被告知9(或任何数字)被视为int,因此精度下降。但那么为什么b=9没有给出任何精度误差的损失?

同样,当写为b+=6时,代码不会给出任何错误。是b=b+6b+=6之间的差异?

任何人都可以解释错综复杂或添加我可能会研究它们的链接吗?

4 个答案:

答案 0 :(得分:4)

此代码出错...

byte b=9;
b=b+6;

...因为b+6发生二进制数字促销,促使bint添加数量。 Section 5.6.2 of the JLS谈到这个问题:

  

当运算符将二进制数字提升应用于一对操作数时,每个操作数必须表示可转换为数字类型的值,以下规则适用:

     
      
  1. 如果任何操作数属于引用类型,则进行拆箱转换(第5.1.8节)。

  2.   
  3. 应用扩展基元转换(第5.1.2节)来转换由以下规则指定的一个或两个操作数:

         
        
    • 如果任一操作数的类型为double,则另一个操作数转换为double。

    •   
    • 否则,如果任一操作数的类型为float,则另一个操作数转换为float。

    •   
    • 否则,如果任一操作数的类型为long,则另一个操作数转换为long。

    •   
    • 否则,两个操作数都将转换为int

    •   
  4.   

(强调我的)

要让b=b+6进行编译,您可以将结果显式地转换回byte

b = (byte) (b + 6);

但是b=9b+=6呢?为什么他们编译没有错误?

9是一个常量表达式,Java编译器对它的处理方式也有所不同。

Section 5.2 of the JLS谈论转让转化。

  

此外,如果表达式是byte,short,char或int类型的常量表达式(第15.28节):

     

如果变量的类型是byte,short或char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示。

如果它是一个常量表达式,它可以缩小,以便编译器知道该值,并且它知道不会发生溢出。这就是b=9不是错误的原因。

Section 15.26 of the JLS讨论了复合赋值运算符。

  

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

也就是说,即使将结果提升为int,结果也会隐式返回byte。请注意,这可能会溢出而不会出错; byte += 10009会因溢出而“成功”。

答案 1 :(得分:2)

表达式

b = b + 6

整数运算,为og JLS §4.2.2。如JLS中所述,每个此类操作都是intlong类型(此处为:int)。因此,结果也是类型int,如果要将其分配给此类变量,则必须将其强制转换为byte

另一方面,JLS §15.26.2解释了复合赋值运算符的规则。简而言之:

  

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

这清楚地告诉我们,复合赋值运算符+=隐含地执行了转换。

答案 2 :(得分:1)

在表达式评估期间,由于java中的促销规则,对int进行了隐式类型转换

所以:

byte b=1;
b=b+1;  //will give error

写:

b=(byte)b+1;

以下是您可以参考的一些链接:

Link 1

Link 2

Link 3

答案 3 :(得分:1)

添加字节时,结果为整数,这样就不会出现字节溢出。

你应该尝试施放它:

b=(byte)(b+9);