Java byte轉int時爲什麼要與0xff進行與運算?

先來看個栗子:

 byte[] bs = digest.digest(origin.getBytes(Charset.forName(charsetName))) ;  
          
 for (int i = 0; i < bs.length; i++) {  
     int c = bs[i] & 0xFF ;
     if(c < 16){ 
          sb.append("0");  
     }  
     sb.append(Integer.toHexString(c)) ;  
 }  
 return sb.toString() ;

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位保持不變,這樣做就可以保證和二進制補碼的一致了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章