你真的了解Java中的位操作?

一个人想着一个人 提交于 2020-04-07 13:13:20

位操作谜题

下面这行代码会输出什么?

byte b = -1;
System.out.println(b & 0xff);

一个byte占8位,再和8位都为1的0xff与操作,那么结果应该是它本身才对,可是运行上面的代码输出却是255。 要想读懂上面的代码,首先我们要弄清楚以下几个问题。

Java如何编码正数和负数?

在Java中数值类型的首位(bit)表示符号位,0表示正数,1表示负数。但是需要注意的是,由于Java采用”2的补码“(Two's Complement)编码负数,所以如果把负数的首位改成0,修改后的值和其绝对值并不相等,所以处理负数时要格外小心。

位操作符(Bitwise Operators)的操作数类型是什么?

Java语言规范[2]中明确指出位操作符(Bitwise Operators)只作用于integer类型(其实也可以作用于long类型)。所以如果操作数是byte/short类型,则在位操作之前会被转换成integer类型。详情请参考Java 语言规范 5.6.2. Binary Numeric Promotion

0xff返回的类型是什么?

0xff返回的是32位integer类型。在Java中integer类型(例如1)有三种表示方式:十进制(1)、八进制(01)和十六进制(0x01)。

byte类型如何被转换成integer类型?

在Java中窄类型向宽类型转换时需要进行符号位扩展,如果该byte是负数则左边要补齐相应个数1,如果是正数则要补齐相应个数0.

我们再回头看上面的代码:

b & 0xff

在&操作之前,b被转换成integer类型,左边用符号位1补齐:

11111111 11111111 11111111 11111111

0xff是integer字面量,二进制值为:

00000000 00000000 00000000 11111111

执行&操作,结果为:

00000000 00000000 00000000 11111111

返回结果是integer类型,符号位是0,所以是一个正数,值为255。

下面是一个更复杂的例子,功能是将长度为4的byte数组转换成integer类型:

public class BytesArrayToInt {
    public static void main(String[] args) {
        System.out.println(byteArrayToInt(new byte[]{0x01, 0x01, 0x01, 0x01}));
    }

    public static int byteArrayToInt(byte[] b) {
        if (b.length == 4) {
            return b[0] << 24 | (b[1] & 0xff) << 16 | (b[2] & 0xff) << 8 | (b[3] & 0xff);
        } else {
            throw new InvalidParameterException("The bytes array length must be 4.");
        }
    }
}

参考

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!