Java有两个用于右移的位移操作符:
>> shifts right,and is dependant on the sign bit for the sign of the result
>>> shifts right and shifts a zero into leftmost bits
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/op3.html
这看起来相当简单,所以任何人都可以向我解释为什么这个代码,当bar为-128的值时,为foo产生-2的值:
byte foo = (byte)((bar & ((byte)-64)) >>> 6);
这意味着要做一个8位字节,最左边2位的掩码,并将它们移到最右边的2位.即:
initial = 0b10000000 (-128)
-64 = 0b11000000
initial & -64 = 0b10000000
0b10000000 >>> 6 = 0b00000010
结果实际上是-2,即
0b11111110
IE浏览器. 1s而不是零被移动到左侧位置
最佳答案
这是因为&实际上是对int执行升级 – 这留下了大量的“1”位.然后你向右移动,将最左边的2位保留为0,然后通过转回字节忽略那些最左边的位.
当你将操作分开时,这会变得更清晰:
public class Test
{
public static void main(String[] args)
{
byte bar = -128;
int tmp = (bar & ((byte)-64)) >>> 6;
byte foo = (byte)tmp;
System.out.println(tmp);
System.out.println(foo);
}
}
版画
67108862
-2
所以再做一点算术:
initial = 0b10000000 (-128)
-64 = 0b11000000
initial & -64 = 0b11111111111111111111111110000000 // it's an int now
0b10000000 >>> 6 = 0b00111111111111111111111111100000 // note zero-padding
(byte) (0b10000000 >>> 6) = 11100000 // -2
即使你从&操作(通过那时的铸造),>>>无论如何,将首先将第一个操作数提升为int.
编辑:解决方案是改变你掩盖事物的方式.而不是通过-64屏蔽,而是仅通过128 64 = 192 = 0xc0掩码:
byte foo = (byte)((bar & 0xc0) >>> 6);
这样你真的只剩下你想要的两个位,而不是在最重要的24位中加载1.