【问题标题】:Java - bit shifting with integers and bytesJava - 使用整数和字节进行位移
【发布时间】:2012-09-28 11:50:52
【问题描述】:

考虑以下代码(其中 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 值进行位移?

编辑:在 cmets 之后,这是一个更完整的示例:

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

【问题讨论】:

  • 真正的java错误有行号。
  • bitMask的类型是什么??还有b的类型呢??
  • 如果它们的类型是int,那么在我的编译器上,两个代码都可以正常工作..
  • 您的代码中没有第 68 行...老实说:如果您提供一个完整的示例,最好包括一个 main 方法,这将非常有帮助。作为@RohitJain,我无法重现您的问题。
  • 是的,您应该将其添加到问题中:p

标签: java int byte bit-shift


【解决方案1】:

将您的 shifting 行转换为:-

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

您的 RHS 是一个 int,您需要将其类型转换为 byte..

上面的代码可以正常工作。有或没有bitNumberbytecasting

所以,你也可以有:-

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 上的 byte 变量中容纳该值时,RHS 上的值才会隐式为 typecasted。否则,我们必须执行 Explicit type casting告诉编译器,我们知道自己在做什么,就为我们做吧..

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

  1. varInt1 最初包含 3。所以 RHS 的值计算为 64。虽然这个值可能会适应 LHS 中的 byte 变量,但编译器也知道,可以改变 varInt1 的值strong>.. 那么如果 varInt1 的值在某个阶段更改为 4 怎么办.. 那就不行了.. 这就是不允许的原因。 .
  2. 现在,在这种情况下,由于我们在这里明确使用了 Integer Literal,所以编译器确信它会适应 byte.. 所以它允许 implicit 转换..
  3. 同样,在这种情况下,已知 RHS 将评估为 128 不能容纳在 byte.. 又失败了..

后两种情况与常规变量不同...由于它们被声明为final,因此无法重新初始化它们。因此,编译器可以根据分配的值做出决定..

  1. 在这种情况下,编译器会看到,finalVarInt2 包含值 3。因此,RHS 的计算结果为 64,可以容纳在 LHS 上的 byte 变量中。现在,由于变量是final,它无法更改,而Compiler 知道这一点,因此可以确定 t*他的值将始终为 64 em>*.. 所以编译器允许这样做。

  2. 在最后一种情况下,finalVarInt3 的值为 4.. 类似的推理.. 不适合 LHS,如 RHS 计算结果为 128,无法放入 byte

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我已经省略了演员表,但仍然得到完全相同的错误? bitMask 是一个字节,我应该在之前就说明这一点。
    • java -version 打印:java 版本“1.7.0_06-icedtea”
    • "0x8" 默认是一个整数,afaik。只保留“外部”演员就足够了。
    【解决方案3】:

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

    bitNumber 被标记为 final

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

    bitNumber 不是最终版本

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

    第二个例子有错误,可能是一些优化。如果有人知道原因就太好了;-)

    【讨论】:

      猜你喜欢
      • 2017-01-31
      • 2015-05-07
      • 2015-03-28
      • 1970-01-01
      • 2015-03-21
      • 1970-01-01
      • 1970-01-01
      • 2012-07-10
      • 2015-01-14
      相关资源
      最近更新 更多