按位操作符运算符概述
在java底层里面,用到了很多这种符号,不对这些按位逻辑符号弄清楚,不容易看懂jdk源码,这里对按位符号做一个简单的梳理
运算符 | 用法 | 描述 | |
---|---|---|---|
按位与( AND) | a & b |
对于每一个比特位,只有两个操作数相应的比特位都是1时,结果才为1,否则为0。 | |
按位或(OR) | `a \ | b` | 对于每一个比特位,当两个操作数相应的比特位至少有一个1时,结果为1,否则为0。 |
按位异或(XOR) | a ^ b |
对于每一个比特位,当两个操作数相应的比特位有且只有一个1时,结果为1,否则为0。 | |
按位非(NOT) | ~ a |
反转操作数的比特位,即0变成1,1变成0。 | |
左移(L) | a << b |
将 a 的二进制形式向左移 b (< 32) 比特位,右边用0填充。 |
|
有符号右移 | a >> b |
将 a 的二进制表示向右移b (< 32) 位,丢弃被移出的位。 |
|
无符号右移 | a >>> b |
将 a 的二进制表示向右移b (< 32) 位,丢弃被移出的位,并使用 0 在左侧填充。 |
这里注意,java里面没有无符号左移,因为无符号左移<<<和左移<<是一样的概念
按位逻辑操作符
& (按位与)
对每对比特位执行与(AND)操作。只有 a 和 b 都是 1 时,a AND b 才是 1。与操作的真值表如下:
a | b | a AND b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
上代码:
|
|
| (按位或)
对每一对比特位执行或(OR)操作。如果 a 或 b 为 1,则 a
OR b
结果为 1。或操作的真值表:
a | b | a OR b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
|
|
^ (按位异或)
对每一对比特位执行异或(XOR)操作。当 a 和 b 不相同时,a
XOR b
的结果为 1。异或操作真值表:
a | b | a XOR b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
|
|
~ (按位非)
对每一个比特位执行非(NOT)操作。NOT a
结果为 a 的反转(即反码)。非操作的真值表:
a | NOT a |
---|---|
0 | 1 |
1 | 0 |
|
|
按位移动操作符
<<有符号左移
该操作符会将第一个操作数向左移动指定的位数。向左被移出的位被丢弃,右侧用 0 补充
在数字 x 上左移 y 比特得到 x * 2y
上代码
|
|
>>有符号右移
该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,拷贝最左侧的位以填充左侧。由于新的最左侧的位总是和以前相同,符号位没有被改变。所以被称作“符号传播”。
例如, 9 >> 2
得到 2
|
|
>>>无符号右移
该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,左侧用0填充。因为符号位变成了 0,所以结果总是非负的。(译注:即便右移 0 个比特,结果也是非负的。)
对于非负数,有符号右移和无符号右移总是返回相同的结果。例如, 9 >>> 2
得到 2 和 9 >> 2
相同
但是对于负数却不尽相同。 -9 >>> 2
产生 1073741821 这和 -9 >> 2
不同:
上代码:
|
|
提问时间如下:
首先负数的二进制为什么是这样的?
在计算机中,负数以其正值的补码形式表达,将二进制数按位取反,所得的新二进制数称为原二进制数的反码,然后反码+1就是补码了
例如:9的原码是00000000 00000000 00000000 00001001
反码是11111111 11111111 11111111 11110110
补码是11111111 11111111 11111111 11110111
所以-9是这样的
int在计算机中存储的是4字节,所以有32位,所以这么长,前面正数是因为把前面的0省略了
那么有符号右移和无符号右移有什么区别呢?
一个是copy最左侧的位来填充,一个是用0来填充,所以无符号右移总是一个正数