Java – 用整数和字节进行位移
考虑以下代码(其中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
将您的shifting
线转换为: –
byte bitMask = (byte)(0x8>>(byte)bitNumber);
你的RHS是一个int,你需要将它强制转换为byte。
上面的代码将工作正常..有或没有将bitNumber
为byte
所以,你也可以: –
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<
以下是解释上述行为的一些推理: -
- ,只有当编译器确定它能够在LHS的
byte
变量中容纳该值时,RHS上的值才会被隐式地进行typecasted
。否则,我们必须做Explicit type casting
来告诉编译器,我们知道我们在做什么,只为我们做..
现在让我们逐一考虑所有情况(从上面的代码(1-3,1-2): -
-
varInt1
最初包含3 。 所以RHS的价值评估为64 。 尽管这个值可能适用于LHS中的byte
变量,但编译器也知道,可以更改varInt1
的值。那么如果varInt1
值在某个阶段更改为4 ,那该怎么varInt1
...它将无法工作..这就是为什么不允许.. - 现在,在这种情况下,因为我们在这里明确使用了
Integer Literal
,所以编译器确保它可以容纳在byte
。所以它允许implicit
转换.. - 同样,在这种情况下,已知
RHS
将评估为128
,不能在byte
容纳.. 再次失败 ..
最后两种情况与常规变量不同...由于它们被声明为final
,因此无法重新初始化。因此,编译器可以根据指定的值做出决定。
-
在这种情况下,编译器会看到,
finalVarInt2
包含值3 。 因此, RHS评估为64 ,可以容纳在LHS的byte
变量中。 现在,由于变量是final
,因此无法更改,并且Compiler
知道这一点,因此确保t * 他的值将始终为64
* ..因此编译器允许这样做。 -
在最后一种情况下,
finalVarInt3
值是4 ..类似的推理..不适合LHS ,因为RHS评估为128 ,不能适合byte
在您的第一个示例中,bitnumber是一个int(32位),当您将其转换为字节(8位)时,您将丢失高位24位。 因此你正在失去精确度。 只需关闭演员(字节)即可。
事实上,这不是答案,正确的答案是Rohit Jain所写的,但这是我第一次看到JVM的这种行为,比较这些代码:
bitNumber
标记为final的版本
final int bitNumber = 10; final byte bitMask = 0x8 >> bitNumber;
bitNumber
不是final的版本
int bitNumber = 10; bitNumber = 10; final byte bitMask = 0x8 >> bitNumber;
并且有错误是第二个例子,可能是一些优化。 如果有人知道原因会很棒;-)