9.无符号右移(>>>)
m>>>n:整数m表示的二进制右移n位,不论正负数,高位都补0,实例如下:
5>>>2 :把十进制的数值5右移两位,按如下步骤计算,
把5转位16位的二进制机器数:00000000 00000000 00000000 00000101
按右移原理,将二进制数左移两位:00000000 00000000 00000000 00000001
右移后结果为1
-5>>>2:把十进制的数值-5右移两位,按如下步骤计算,
把-5转位16位的二进制机器数:11111111 11111111 11111111 11111011
按右移原理,将二进制数右移两位:00111111 11111111 11111111 11111110
右移后结果为正数
10.按位非操作(~)
~ 按位取反操作符,对每个二进制位的内容求反,即1变成0,0变成1实例如下
把-5转位16位的二进制机器数:11111111 11111111 11111111 11111011
~(-5) 取反结果:00000000 00000000 00000000 00000100
转为十进制,结果为4
11.按位与操作(&)
& 位与操作符,对应的二进制位进行与操作,两个都为1才为1,其他情况均为0,原理如下:
1&0=0
0&0=0
1&1=1
0&1=0
实例:-5 & 4
-5的二进制形式为: 11111111 11111111 11111111 11111011
4的二进制形式为: 00000000 00000000 00000000 00000100
——————————————————————————————
逻辑与运算结果: 00000000 00000000 00000000 00000000
最终结果为0。
12.按位或操作(|)
| 位或操作符,对应的二进制位进行或操作,两个都为0才为0,其他情况均为1,原理如下:
1|0=1
0|0=0
1|1=1
0|1=1
实例:-5 | 4
-5的二进制形式为:11111111 11111111 11111111 11111011
4的二进制形式为:00000000 00000000 00000000 00000100
————————————————————————————
逻辑或运算结果: 11111111 11111111 11111111 11111111
最终结果为-1。
利用或的原理我们可以把字节转换为整数,-64&0xFF=192,其中0xFF表示整数255。
13.按位异或操作( ^ )
^ 异或操作符,相同位值为0 否则为1,原理如下:
1^1=0
1^0=1
0^1=1
0^0=0
实例:-5 ^ 4
-5的二进制形式为:11111111 11111111 11111111 11111011
4的二进制形式为:00000000 00000000 00000000 00000100
————————————————————————————
逻辑异或运算结果: 11111111 11111111 11111111 11111111
最终结果为-1。
其实利用逻辑异或操作有个作用就是可以比较两个数值是否相等,即利用11=0,00=0的原理,如5^5==0。
14.总结
通过上面的分析,我们对java的位运算也算有了比较全面的了解,那么我们的程序通过位运算又有什么优势呢?其实通过位运算确实会比我们直接的程序代码运算会快很多,因为位运算直接运算的是计算机底层的二进制机器操作指令,而我们的程序代码运算最终也是要转成计算机可识别的二进制操作指令才能执行,位运算可以理解为省了中间转换的操作,处理器可以直接操作。事实是我们在某些源码经常能看见如下代码:
HashMap.class
/** * Returns a power of two size for the given target capacity. */ static final int tableSizeFor(int cap) { int n = cap - 1; n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16; return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; }
其实原理是一样的,处理器能够直接支持和处理。