Java 定义的位运算(bitwise operators)直接对整数类型的位进行操作,这些整数类型包括 long,int,short,char 和 byte。
位运算符主要用来对操作数二进制的位进行运算。按位运算表示按每个二进制位(bit)进行计算,其操作数和运算结果都是整型值。
Java 语言中的位运算符分为位逻辑运算符和位移运算符两类,下面详细介绍每类包含的运算符。
位逻辑运算符
运算符 | 含义 | 实例 | 结果 |
& | 按位进行与运算(AND) | 4 & 5 | 4 |
| | 按位进行或运算(OR) | 4 | 5 | 5 |
^ | 按位进行异或运算(XOR) | 4 ^ 5 | 1 |
~ | 按位进行取反运算(NOT) | ~ 4 | -5 |
位与运算符
位与运算符为&,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位同时为 1,那么计算结果才为 1,否则为 0。因此,任何数与 0 进行按位与运算,其结果都为 0。
0000 0000 0000 1111
& 0000 0000 0000 0000
——————————
0000 0000 0000 0000
位或运算符
位或运算符为|,其运算规则是:参与运算的数字,低位对齐,高位不足的补零。如果对应的二进制位只要有一个为 1,那么结果就为 1;如果对应的二进制位都为 0,结果才为 0。
11|7
0000 0000 0000 1011
| 0000 0000 0000 0111
——————————
0000 0000 0000 1111
位异或运算符
位异或运算符为^,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位相同(同时为 0 或同时为 1)时,结果为 0;如果对应的二进制位不相同,结果则为 1。
11^7
0000 0000 0000 1011
^ 0000 0000 0000 0111
——————————
0000 0000 0000 1100
位取反运算符
位取反运算符为~,其运算规则是:只对一个操作数进行运算,将操作数二进制中的 1 改为 0,0 改为 1。
~10
~ 0000 0000 0000 1010
__________________
1111 1111 1111 0101
编译执行以上程序,会发现输出的结果是 -11,而不是 65525。这是因为取反之后的结果是十六进制数,而在上面的程序中使用 %d 将输出转换为了十进制数。
可以使用如下语句查看十六进制结果。
可以看到输出结果为 fff5,将它转换为二进制是 1111111111110101。这个二进制数的最高位为 1,表示这个数为负数。除最高位外,按位取反再加 1,即得到二进制原码 1000000000001011,用十进制数表示即为 -11。
注意:位运算符的操作数只能是整型或者字符型数据以及它们的变体,不用于 float、double 或者 long 等复杂的数据类型。
位移运算符
- “<<” :左移运算符,按照操作符右侧指定的位数将操作符左边的操作数向左移动(在低位补0);
- “>>” :右移运算符,按照操作符右侧指定的位数将操作符左边的操作数向右移动;
- “有符号”右移操作符使用“符号扩展”:
- 若符号为正,则在高位插入0;
- 若符号为负,则在高位插入1。
- “>>>”:“无符号”右移操作符,它使用“符号扩展”:无论正负都在高位插入0。
这里的位移运算符其实是对补码进行操作。
左位移运算符
左移位运算符<<,其运算规则是:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。
11<<1
0000 0000 0000 1011
——————————
0 0000 0000 0001 0110
^
舍弃
-3的补码是 1111 1111 1111 1111 1111 1111 1111 1101;
-3左移一位:
补码变为:1111 1111 1111 1111 1111 1111 1111 1010;
对补码再取补,得到对应的原码。
对应原码:1000 0000 0000 0000 0000 0000 0000 0110;
即 -3 ==> -6 (10进制);
右位移运算符
右位移运算符为»,其运算规则是:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。
3>>1
0000 0000 0000 0000 0000 0000 0000 0011
==> 0000 0000 0000 0000 0000 0000 0000 0001
-3的补码是 1111 1111 1111 1111 1111 1111 1111 1101;
-3右移一位:
补码变为:1111 1111 1111 1111 1111 1111 1111 1110;^
对补码再取补[取反+1],得到对应的原码。
对应原码:1000 0000 0000 0000 0000 0000 0000 0010;
即 -3 ==> -2 (10进制);
无符号右移
无符号右移其实就是将符号位也当成一个普通的位,因为正数的符号位为0,所以对正数来说,无符号右移跟有符号右移是一样的。而对负数来说,无符号右移是在高位插入0,而有符号右移是在高位插入0。
-3无符号右移1位过程:
原码:1000 0000 0000 0000 0000 0000 0000 0011;
补码:1111 1111 1111 1111 1111 1111 1111 1101;
无符号右移:0111 1111 1111 1111 1111 1111 1111 1110;
再求补转原码:0111 1111 1111 1111 1111 1111 1111 1110;
注意: 此时在转换成10进制时,仍认为最高位为符号位。而右移后最高位为0,即正数,而对正数再求补仍是这个数。
即 -3 ==> 2147483646 (10进制)。
复合位赋值运算符
运算符 | 含义 | 实例 | 结果 |
&= | 按位与赋值 | n1 &= n2 | n1 = n1 & n2 |
|= | 按位或赋值 | n1 |= n2 | n1 = n1 | n2 |
^= | 按位异或赋值 | n1 ^= n2 | n1 = n1 ^ n2 |