Java 总是把 byte 当做有符处理,我们可以通过将其和 0xFF 进行二进制与得到它的无符值。
public static void main(String[] args) {
int num = 0xde;
System.out.println("原始数据[0xde]:" + num);
byte a = (byte) 0xde;
System.out.println("强转为byte类型后[(byte)0xde]:" + a);
int b = a & 0xff;
System.out.println("二进制与后[((byte)0xde)&0xff]:" + b);
}
运行结果
原始数据[0xde]:222
强转为byte类型后[(byte)0xde]:-34
二进制与后[((byte)0xde)&0xff]:222
原理解释
先来看一下【0xde】的原码:
0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 1 1 0 1 1 1 1 0
计算结果为 222。
强制转换: 丢掉前面三个字节,所以a的原码为 【1 1 0 1 1 1 1 0】。在Java中,byte是被当作有符数处理的,取值范围为【-128 ~ 127】。正数用原码表示,负数用补码表示。最高位代表符号位(1为负数,0为正数)。最高位为1,所以为负数。现在看它的补码(反码+1):
1 0 1 0 0 0 0 1
+ 0 0 0 0 0 0 0 1
---------------------
= 1 0 1 0 0 0 1 0
补码:【1 0 1 0 0 0 1 0】,计算出的结果为-34。
但是,这个补码对于-34来说,就是它的原码。但是在计算机中运算时,都是通过补码运算的。我们要把它再转成补码:
1 1 0 1 1 1 0 1
+ 0 0 0 0 0 0 0 1
---------------------
= 1 1 0 1 1 1 1 0
将它再和oxff进行二进制与,就可以得到它的无符号数了。
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0
& 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
---------------------------------------------------------------------
= 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 0
现在再来看一下b的原码:
0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 1 1 0 1 1 1 1 0
运算结果为222.
同时,我们可以得出一个结论:补码的补码为原码