最近在查看java源码, 其实大量用到了位运算,在看到下面的代码时困惑了
<span style="white-space:pre"> </span>long msb = 0;
long lsb = 0;
for (int i=0; i<8; i++)
msb = (msb << 8) | (data[i] & 0xff);
for (int i=8; i<16; i++)
lsb = (lsb << 8) | (data[i] & 0xff);
上面的java源码中为什么会用到data[i]&0xff来做处理, 而不是用过data[i]与变量msb做‘与运算’?
1.先说0xFF
java创建的数字,默认都给被赋予32位的内存空间,这个是java的内部机制,那么十六进制表示的oxff的所占用的空间用完全的十六进制表示应该为"0x0000 00FF";
2.再说位运算
首先得问题是:数字在进行位运算时,如果声明的数据类型少于32位,则会提升到32位数据后,进行运算;
java位运算包括‘与[&]’、‘或[|]’、‘非[~]’、‘异或[^]’; 和左移、右移[符号右移、无符号右移]
左移即数字的二进制格式向左移动, 低位补0;如“0010 1001” <<2 , 结果为1010 0100
右移即数字的二进制格式向右移动,这里分‘符号右移’和‘无符号右移’。
符号右移即向右移动,正数则高位补0, 负数则高位补1;
如(41)‘0000 ...... 0010 1001’>>2, 结果为0000 1010(12)
( -23)‘1111 ...... 1110 1001’>>2, 结果为1111 1010(-6)
无符号右移即向右移动,高位补0;如(41)‘0000 ...... 0010 1001’>>2, 结果为0000 ...... 0000 1010
(-23)‘1111 ...... 1110 1001’>>>2, 结果为0011 ...... 0011 1010
与运算: 真真为真,否则为假; 如:0101 & 1001 = 0001
或运算: 假假为假,否则为真; 如:0101 | 1001 = 1101
非运算: 二进制位取反 如:~0101 = 1010
异或: 真假为真,否则为假 如: 1011^ 0101 = 1110
3.回到我们原来问题
"byte[i]"是指的一个byte类型数据, 假设为‘-6’, 二进制为: 1111 1010;
0xFF的实际内存空间为0x0000 00FF,是32位的数据。二进制位:0000 ......1111 1111
在进行&运算的时候,首先会将byte[i]的实际内存提升为32位, 正数则高位补0,负数则高位补0。 如下:
1111 1111 1111 1111 1111 1111 1111 1010
& 0000 0000 0000 0000 0000 0000 1111 1111
------------------------------------------------------------------------------------
0000 0000 0000 0000 0000 0000 1111 1010
结果为最后8位(即FF表示的位数)为byte[i]的值, 前24位都为0;
至此,我们明白这里的byte[i]&0xFF的意义是“取到二进制的最后8位【即两个十六进制的值】”