参考:https://www.cnblogs.com/yongdaimi/p/5899362.html
============================================================
总结:在java中,对byte和short类型的 右移操作 必须先进行 & 0xff 后再右移,避免byte或short是负数的情况下,导致 右移操作前 自动升为int,前面补了很多1,此时右移会把1冲到高位上,从而错误;
int 和 long没有任何问题;
左移没有这个问题,因为左移及时自动转换成int 在前面补了很多1后,后面的截断 还是会把左边的都截掉,就是说 左移 永远是从右边补0,而右移由于自动转换成int的存在,会导致即使使用了>>>的情况下
左边还是会补1,因为负数转换成int的时候,前面的每一位都是1了。留意。
((bytes[0] & 0xff) >>> 3);
1.举例:
public static void main(String[] args) { byte[] bytes = new byte[1]; bytes[0] = 31;//00011111 bytes[0] <<= 3;//11111000 bytes[0] >>>= 3;// 这步很诡异的变成了 11111111 ???? System.out.println(bytes[0]);// -1;最终的结果为-1??? }
接下来调试看下:
导致输出的结果为-1,而不是31的原因是,在java中 对byte和 short进行位操作的话,会先默认自动转换为int 再进行位操作;
public static void main(String[] args) { byte[] bytes = new byte[1]; bytes[0] = 31;//00011111 /* bytes[0] <<= 3;这步发生的情况如下: 0000 0000 0000 0000 0000 0000 0001 1111(先把byte[0]转换成int) 0000 0000 0000 0000 0000 0000 1111 1000(再左移3位) 1111 1000(再赋值给byte[0],截断) */ bytes[0] <<= 3; /* bytes[0] >>>= 3; 又发生了什么: 1111 1111 1111 1111 1111 1111 1111 1000(把当前的byte[0]转换成int,由于是负数,所以转换成了这样,左边按符号位全部补1,就是由这步自动转换导致了问题,解决方法就是把这步自动转换前面的1去除,用 & 0xff) 0001 1111 1111 1111 1111 1111 1111 1111(右移3位) 1111 1111(赋值截断,最终 byte[0]的值,可见变成全是1了) */ bytes[0] >>>= 3; /* 输出byte[0]发生了什么,输出byte[0]就是把byte[0]的值转换成10进制,计算机发现byte[0]的最高位是1,说明是负数, 计算机认为它是负数后,负数在计算机中是以补码的方式来存储的,所以具体的10进制的值是它的原码,需要把补码转换成原码 规则:1.补码符号位不变,其余位取反; 2.取反后加1,就是原码 1000 0000(符号位不变,其余位取反) 1000 0001(取反后加1,就是原码) 原码就是具体的值,可见是-1 */ System.out.println(bytes[0]); }
解决方法,系统自动把byte[0]由byte自动向int 转换后的值再与0xff取与运算,使其一个字节的前面的位全部为0:
1111 1000 --> 1111 1111 1111 1111 1111 1111 1111 1000(自动向int转换)
然后我们再通过& 0xff 让它们取与运算:
1111 1111 1111 1111 1111 1111 1111 1000
0000 0000 0000 0000 0000 0000 1111 1111
=
0000 0000 0000 0000 0000 0000 1111 1000(这个才是我们想要的)
与&0xff 运算后,再说右移的事,就解决了这个问题;
总结:在java中,操作byte右移前一定要先 &0xff 做与运算,才能右移;
public static void main(String[] args) { byte[] bytes = new byte[1]; bytes[0] = 31;//00011111 bytes[0] <<= 3; bytes[0] = (byte) ((bytes[0] & 0xff) >>> 3); System.out.println(bytes[0]); }
==================================================================================================================
接下来看下short:
看下 int :
看下long: