总归就是一句话,保证补码的完整性
先看例子
byte[] b = new byte[1];
b[0] = -127;
// -127
System.out.print(b[0]);
// 129
System.out.print(b[0] & 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);