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

原创
2016/10/31 17:48
阅读数 975

位操作谜题

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

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.");
        }
    }
}

参考

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
1 收藏
1
分享
返回顶部
顶部