在Java中byte類型是有符號的,而Java中又沒有提供無符號的byte類型,因此在其表示範圍爲-128-127之間。而這樣對於一些I/O處理程序來說需要對考慮符號位問題,通常的做法可能是:
int unsignedByte = signedByte >=0 ? signedByte : signedByte + 256;
這裏我們發現,由於byte的符號位的關係,我們不得不採用長度更長的int類型來處理符號位帶來的問題。因此,我們會覺得byte由於要考慮符號位其範圍變小了,所以,我們只好通過int來處理。在這個類型的轉換過程中,任意長度的int類型會截斷其高位的字節來適應byte類型,因爲int類型要比byte類型寬。這也就是爲什麼一個int的127轉換成了byte還是一個127。
不過,我們考慮另外一種情況,就是當一個int值大過byte表示的數值範圍的時候,這個時候問題就出現了。比如,int的128轉換成一個byte類型會是-128。這是因爲補碼運算的關係造成的。首先,128寫成16進制是0x00000080,當做int到byte的類型轉換的時候,前面的0被截斷形成0x80。在二進制中0x80可以寫成10000000,如果這是一個無符號數哪麼一切正常,但是如果是一個有符號數就會經過補碼運算。對於負數而言,其補碼運算就是反碼(就是1轉換成0並且反正既然)加一。哪麼,10000000的補碼就是01111111加一,即10000000=128(十進制)。因此,byte0x80事實上表示的也
就是-128了。類似的int類型的129就是byte類型的-127,而int類型的130則是byte類型的-126,等等,直到int的255對應爲byte的-1。
哪麼如果到了256呢?此時,地位的字節被0來填充,簡而言之256就是0x00000100。因此,轉換成byte就是0,這個轉換循環也就是256個。因此,我們根據上述原理,得出如下規律:
byte byteValue=0;
int temp = intValue % 256;
if ( intValue < 0) {
byteValue = (byte)(temp < -128 ? 256 + temp : temp);
}
else {
byteValue = (byte)(temp > 127 ? temp - 256 : temp);
}
上述過程中,我們既可以把有符號的byte轉換成無符號的byte(用int類型存儲),也可以把有符號但可能超出byte範圍的數據轉換成有符號的byte。
在剖析該問題前請看如下代碼
public static String bytes2HexString(byte[] b) {
String ret = "";
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[ i ] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
ret += hex.toUpperCase();
}
return ret;
}
上面是將byte[]轉化十六進制的字符串,注意這裏b[ i ] & 0xFF將一個byte和 0xFF進行了與運算,然後使用Integer.toHexString取得了十六進制字符串,可以看出
b[ i ] & 0xFF運算後得出的仍然是個int,那麼爲何要和 0xFF進行與運算呢?直接 Integer.toHexString(b[ i ]);,將byte強轉爲int不行嗎?答案是不行的.
其原因在於:
1.byte的大小爲8bits而int的大小爲32bits
2.java的二進制採用的是補碼形式
問題1:java中沒有實現這種“byte a = 0xB2 --> String b = “B2””轉換的簡單實現需要自己實現。
答:自己編寫的轉換函數,思路將byte的高低4位分開,分別轉換爲對應的字符然後合成返回的字符串。
未解決的疑問在java中不存在類似C中的無符號量,所以如果一個字節超過0x80其對應的整型值即爲負值,但在高位右移4位後還是負值,且與對應的正值相差16,比如0xB2經過右移後的期望值是0x0B(11)但實際值是-5與預期的值相差16(這個16通過多次試驗得出),對此現象爲找到合理的解釋。
問題2:“String a=”B2” --> byte b=0xB2”字符的byte轉換爲byte數據類型
答:思路通過Integer作爲轉換的中間橋樑
問題3:整數(表示範圍限定爲兩個字節unsigned short)通過Integer.byteValue()轉換成byte[2],如果超出一個byte的表示範圍將會截斷高位的值。
答:思路一個byte能表示的最大整數爲256(超過128爲負值,超過256將被截斷),所以取256的倍數爲byte[0],256的餘數爲byte[1]。