Java错误:可能会丢失精度。

6

我正在制作一个小型的Java程序,用于加密任何类型的文件。我的做法是:打开输入文件,将其读入一个与该文件大小相同的字节数组中,然后进行编码,并将整个数组写入名为output.dat的.dat文件中。为了对字节数组进行索引,我使用了一个int类型的变量。代码如下:

        for(int i : arr) {
            if(i>0) {
                arr[i] = arr[i-1]^arr[i];
            }
        }

'arr'是一个字节数组,大小与输入文件相同。

我遇到的错误:CodingEvent.java:42: 错误:可能会丢失精度

arr[i] = arr[i-1]^arr[i];

(箭头指向^运算符)

需要类型:byte

找到类型:int

怎么了?能帮我吗?

4个回答

7
< p > byte ^ byte 的结果是,令人感到反直觉的是 int。在将其赋回到 arr[i] 时,对表达式的结果使用强制类型转换:

arr[i] = (byte)(arr[i-1]^arr[i]);

这是因为该运算符被定义为对其操作数执行二进制数字提升,因此它在这种情况下实际执行的操作是:
arr[i] = (int)arr[i-1]^(int)arr[i];

...这自然导致了int。这就是我们需要转换回来的原因。


1
^ 运算符的操作数首先会 转换为 int(这称为二进制数值提升)。因此,两个 byte 类型(arr[i-1]arr[i])都会被转换为一个 int 类型,而操作的结果也是一个 int 类型。
你需要将结果强制转换回 byte 类型,然后再将其赋值给 arr[i]

1
哈哈!我们都提到了二进制数字转换。这也太极客了吧。 - T.J. Crowder

0

看一下JLS 15.22.1

当运算符 &, ^ 或 | 的两个操作数都是可转换为原始整型类型(§5.1.8)的类型时,首先对操作数执行二进制数字提升(§5.6.2)。

以及JLS 5.6.2

1.如果任何操作数是引用类型,则将其进行解包转换(§5.1.8)。

2.按照以下规则,将扩展原始转换(§5.1.2)应用于将一个或两个操作数转换:

  1. 如果任一操作数为double类型,则将另一个操作数转换为double类型。

  2. 否则,如果任一操作数为float类型,则将另一个操作数转换为float类型。

  3. 否则,如果任一操作数为long类型,则将另一个操作数转换为long类型。

  4. 否则,两个操作数都将转换为int类型。

因此,以下表达式首先被转换为int类型。

arr[i-1]^arr[i];

要将其转换回 byte,请使用显式转换:

arr[i] = (byte)(arr[i-1]^arr[i]);

0
如果arr[]的类型是byte[],那么这就是问题所在。当Java使用整数进行任何二进制操作时,它会根据运算符返回一个int或long。在这种情况下,arr[i-1]^arr[i]的结果是一个int,而你试图将其存储在一个byte中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接