Java - 用整数和字节进行位移

时间:2012-09-28 11:50:52

标签: java int byte bit-shift

考虑以下代码(其中byteIndex是int):

int bitNumber = b-(8*byteIndex);
bitMask = 0x8>>(byte)bitNumber;

这会产生错误

error: possible loss of precision

编译时(必需字节,找到int)。

代码

int bitNumber = b-(8*byteIndex);
bitMask = 0x8>>2;

编译好。

这里有什么问题,如何修复第一个允许按int值移位的示例?

编辑:在评论之后,这是一个更完整的例子:

48) int byteIndex;
49) byte bitMask;
50) int bitNumber;
    // assign value to byteIndex
67) bitNumber = b-(8*byteIndex);
68) bitMask = 0x8>>bitNumber;

,给出的错误是:

...MyClass.java:68: error: possible loss of precision
    bitMask = 0x8>>bitNumber;
             ^
  required: byte
  found:    int
1 error

3 个答案:

答案 0 :(得分:8)

shifting行转换为: -

byte bitMask = (byte)(0x8>>(byte)bitNumber);

您的RHS是一个int,您需要将其强制转换为字节..

以上代码可以正常工作..无论有没有casting bitNumberbyte

所以,你也可以: -

byte bitMask = (byte)(0x8>>bitNumber);

但是,这是一个问题 - byte bitMask = 0x8>>3;工作得很好..为什么会这样?

以下是一些示例,用于解释其工作背后的原因以及final的行为: -

byte bitMask;
int varInt1 = 3;
final int finalVarInt2 = 3;
final int finalVarInt3 = 4;

bitMask = 0x8>>varInt1;    // 1. Will not work. 
bitMask = 0x8<<3;          // 2. Will work

bitMask = 0x8<<4;          // 3. Will not work
bitMask = 0x8<<finalVarInt2;   // 1. Will work
bitMask = 0x8<<finalVarInt3;   // 2. Will not work

以下是解释上述行为的一些推理: -

  • 只有当编译器确定它能够在LHS的typecasted变量中容纳该值时,RHS上的值才会隐式byte。否则,我们必须做Explicit type casting告诉编译器,我们知道我们在做什么,只为我们做..

现在让我们逐一考虑所有情况(来自上面的代码(1-3,1-2): -

  1. varInt1 最初包含 3 。因此 RHS 的值评估为 64 。虽然此值可能适用于 LHS 中的 byte 变量,但编译器也知道,可以更改 {{1 }} ..那么,如果 varInt1 的值在某个阶段更改为 4 ,那该怎么办呢......那就不行了..那是为什么不允许..
  2. 现在,在这种情况下,由于我们在此明确使用了 varInt1 ,因此编译器确保它可以容纳 Integer Literal ..所以它允许 byte 施放..
  3. 同样,在这种情况下,众所周知 implicit 会评估为 RHS 128 byte .. 再次失败 ..
  4. 最后两种情况与常规变量不同...由于它们被声明为 final ,因此无法重新初始化..所以,编译器可以根据指定的值做出决定..

    1. 在这种情况下,编译器会看到, finalVarInt2 包含值 3 。因此, RHS 评估为 64 ,可以在 LHS 上的 byte 变量中进行调整。现在,由于变量 final ,因此无法更改,Compiler知道这一点,因此确保t * 的值始终为{ {1}} * ..所以编译器允许这样做。

    2. 在最后一种情况下, 64 的值为4.类似的推理..不适合 LHS ,因为 RHS 评估为 128 ,这不符合 finalVarInt3

答案 1 :(得分:1)

在您的第一个示例中,bitnumber是一个int(32位),当您将其转换为一个字节(8位)时,您将丢失高位24位。因此你正在失去精确度。只需离开演员表(字节)。

答案 2 :(得分:0)

实际上这不是答案,正确的答案是Rohit Jain所写的,但这是我第一次看到JVM的这种行为,比较这些代码:

bitNumber标记为最终

的版本
final int bitNumber = 10;
final byte bitMask = 0x8 >> bitNumber;

版本bitNumber不是最终版

int bitNumber = 10;
bitNumber = 10;
final byte bitMask = 0x8 >> bitNumber;

还有错误是第二个例子,可能是一些优化。如果有人知道原因会很棒; - )