byte数据溢出

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.

同时,我们可以得出一个结论:补码的补码为原码

猜你喜欢

转载自blog.csdn.net/yujiumin/article/details/81001666