我們查看很多源碼的時候都會看到在byte轉int的時候會&0xff,為什么會有這個操作呢。
byte[127]轉int
看下面代碼:
byte[] b = new byte[1];
b[0] = 127;
// 127
System.out.print(b[0]);
// 127
System.out.print(b[0] & 0xff);
兩者的輸出都為127,看不出有什么問題。
byte[-127]轉int
我們將數值改為-127時
byte[] b = new byte[1];
b[0] = -127;
// -127
System.out.print(b[0]);
// 129
System.out.print(b[0] & 0xff);
為什么&0xff反而數值變得奇怪了呢。
數據擴展
眾所周知計算機內二進制都是以補碼形式存儲的。byte類型的長度為8bit,而int類型為32bit。
在將低精度轉成高精度數據類型,有兩種擴展方案。
(1)補零擴展,能夠保證二進制存儲的一致性,但不能保證十進制值不變
(2)符號位擴展,能夠保證十進制值不變,但不能保證二進制存儲的一致性
正數
對於正數來說這兩種是一樣的。當b[0] 為127的時候,b[0] 補碼為01111111
1.補零擴展以后為00000000 00000000 00000000 01111111
2.符號位擴展以后也為00000000 00000000 00000000 01111111
負數
對於負數來說就不一樣了。當b[0] 為-127的時候,b[0] 補碼為10000001
1.補零擴展以后為00000000 00000000 00000000 10000001
2.符號位擴展以后為11111111 11111111 11111111 10000001
tips:Java對於有符號的擴展,使用的是符號位擴展來保證十進制的值不變。
即擴展以后為11111111 11111111 11111111 10000001,其原碼就為10000000 00000000 00000000 01111111,其十進制值為-127
但是其二進制表示發生了變化補碼從10000001變為了11111111 11111111 11111111 10000001。
使用&0xff
所以很多時候為了保證低八位的二進制不變,使用&0xff
`11111111 11111111 11111111 10000001 & 0xff =
11111111 11111111 11111111 10000001 & 11111111 =
00000000 00000000 00000000 10000001` 但是十進制變成了 129
實例 byte[]轉為int
我們用實例看一下&0xff對轉換時的影響,如下所示我們期望得到的int00000000 00000000 00000001 10000001十進制為385,如果不加&0xff則會得到-127。
tips:java 中對byte的所有運算操作均會是首先將byte轉化為int, 再行運算
byte[] bs = new byte[4];
// 10000001
bs[0] = (byte) -127;
// 00000001
bs[1] = (byte) 1;
// 00000000
bs[2] = (byte) 0;
// 00000000
bs[3] = (byte)0;
// (bs[0]&0xff):00000000 00000000 00000000 10000001 或
// (bs[1]&0xff):00000000 00000000 00000001 00000000
// -----------------------------------
// 00000000 00000000 00000001 10000001 或
// (bs[2]&0xff):00000000 00000000 00000000 00000000
// -----------------------------------
// 00000000 00000000 00000001 10000001 或
// (bs[3]&0xff):00000000 00000000 00000000 00000000
// -----------------------------------
// 00000000 00000000 00000001 10000001 正數 = 256+128+1=385
int i = (bs[0]&0xff) | ((bs[1]& 0xff)<<8)| ((bs[2]& 0xff)<<16) | ((bs[3]& 0xff)<<24);
// bs[0]:11111111 11111111 11111111 10000001 或
// bs[1]:00000000 00000000 00000001 00000000
// -----------------------------------
// 11111111 11111111 11111111 10000001 或
// bs[2]:00000000 00000000 00000000 00000000
// -----------------------------------
// 11111111 11111111 11111111 10000001 或
// bs[3]:00000000 00000000 00000000 00000000
// -----------------------------------
// 這里得到的是補碼(負數),需要轉成原碼
// 11111111 11111111 11111111 10000001 - 1
// 11111111 11111111 11111111 10000000 取反
// 10000000 00000000 00000000 01111111 = -127
int k = (bs[0]) | ((bs[1])<<8)| ((bs[2])<<16) | ((bs[3])<<24);
// 385
System.out.print(i);
// -127
System.out.print(k);
