先来看个栗子:
|
bs是由一段字符串经过MD5加密后输出的byte数组。在for循环里,bs[i]是一个8位二进制,而0xFF的二进制为11111111,那么bs[i]与0xFF进行与运算,得到仍为bs[i],不是多此一举吗,为什么要这样做呢?
在搞清楚之前,需要理解计算机存储机制以及原码、反码、补码的概念:
在学计算机原理时,知道计算机内部的存储都是利用二进制的补码进行存储的,如果用1个字节表示一个数字,一个字节有8位,超过8位就进1,在内存中的情况为:100000000,进位1被丢掉。
来回顾下反码、补码的概念:
反码
对于正数,反码和原码相同;
对于负数:反码是除符号位1之外的都取反。
补码:就是对反码加1
比如:
-1 的原码:10000001
-1 的反码:11111110
+1
-1 的补码:11111111
0 的原码:00000000
0 的反码:11111111(正零和负零的反码相同)
+1
0 的补码:100000000 (1丢掉,正零和负零的补码相同)
-----------------------------------------------------------------------------------
由上述可知,byte a = -127(原码:11111111)在内存中会以其补码(10000001)的形式存储,在做byte -> int类型转换时,JVM会做一个补位处理,由于int类型为32位,所以补位后的补码为:11111111 11111111 11111111 10000001(32位),这个32位二进制补码也是-127。(注:补位是补1还是补0,取决于byte的最高位是1还是0)
我们发现,在byte -> int转换时,计算机存储的补码和JVM补位后的补码表示的十进制数字仍然是相同的。
所以,在byte类型转为int类型时,为什么要和0xFF(原码:11111111)做与运算?其本质原因是要和二进制补码保持一致。当byte转int时,高24位必然会补1,这时与其二进制补码已经不一样了,补位后的补码与0xFF 做与运算,可以将高24位置为0,低8位保持不变,这样做就可以保证和二进制补码的一致了。