java的byte陣列的不同寫法

lvxiangan發表於2014-11-20

經常看到java中對byte陣列的不同定義,粗略整理的一下:
一個位元組(byte)=8位(bit),“byte陣列”裡面全部是“byte”,即每一個byte都可以用二進位制、十六進位制、十進位制來表示。

 

首先八位二進位制數0000 0000 ~1111 1111,一共可以表示2^8=256位數,
如果想要表示無符號整數,可以表示0~255。
如果想要表示有符號整數,將
左邊第一位作為符號位,即0代表正數,1代表負數,後面7位數值域可以表示0~127,這就是原碼定義。

我們先來看看8位二進位制:00010110,

  • 當把它看作無符號數時,計算方法如下:
    二進位制:00010110 ------> 0*2^7 + 0*2^6 + 1*2^5 + 0*2^4 + 1*2^3 + 1*2^2 + 0*2^1 + 0*2^0 = 22
  • 當把它看作有符號數時,左邊第一位0表示正數,只計算後面7位,計算方法如下:
    二進位制:00010110 ------> 0*2^6 + 1*2^5 + 0*2^4 + 1*2^3 + 1*2^2 + 0*2^1 + 0*2^0 = 22

Java沒有無符號型別,全部是有符號型別的資料型別。但是其它語言,如C語言的unsigned short 無符號數,它值的範圍就是要從0開始,並且比java的short型別儲存的資料範圍更大。
因為java只有有符號的資料型別,如short 的表示範圍 -128到+127,這就是代表有符號的資料型別了。

在實際開發中,可能要與C寫的硬體介面,網路介面相互直接資料互動,此時由於java沒有無符號的資料型別,導致java與C看似相同的資料型別,其實儲存空間確是不同的,這個問題解決方法是java用更高的儲存資料型別,如果C用int,你的java就要考慮用Long或者BigInteger了。還有一種方法就是用java的guava框架來實現你的目標了。

 

在Java工程程式碼中

二進位制:00010110 ------> 0*2^7 + 0*2^6 + 1*2^5 + 0*2^4 + 1*2^3 + 1*2^2 + 0*2^1 + 0*2^0 = 22
16進位制:  0x16 ----------> 1*16^1 + 6*16^0  = 22
十進位制:22

所以下面三者等價:

byte [] aa = {00010110,  01010010,  10111000};
byte [] aa = {0x16,      0x52,      0xB8};
byte [] aa = {22,        82,        184};

  • 在Eclipse斷點除錯的時候,看到的byte陣列內容都是用十進位制表示
  • 有時會看到負數,是因為:java讀取的方式只支援位元組陣列,一個byte = 8位,所以一個byte容量不能超過127,如果超過就會溢位,以負數的形式顯示。
  • 溢位原因如下:java採用補碼儲存整數,int型為32位二進位制,byte為8位二進位制 

那麼130在記憶體中的表示形式:00000000 00000000 00000000 10000010  
這樣擷取後8位就變成10000010,補碼錶示的時候第一位是符號位,0正1負,所以可以知道10000010肯定是一個負數,
再來看它的數值部分,補碼由正數變負數,還是正數變負,方法:“按位取反,再加1”,所以後7位:0000010應該變為1111101 + 1 = 1111110(即126)  

又因為是負數,所以就擷取變成-126了

 

我們再來看下-130的例子(符號位是1,其餘按位取反+1)  
-130在記憶體中的表示形式:11111111 11111111 11111111 01111110  
這樣擷取後8位就變成01111110,顯然這是整數啊,然後數值部分是126  
64+32+16+8+4+2=126 

 

 

相關文章