Java中位运算符
Java都是提供了哪些位运算符,通过JDK官方文档,我们可以知道,Java中有以下为运算符:左位移(<<),右位移(>>),无符号右位移(>>),按位与(&),按位或(|),按位非(~),按位异或(^) ,共七种位运算符,除了按位非是一元运算符,其他的都是二元运算符。
对于位移运算符来说,有一点需要注意,就是如果操作符左边是int类型,则操作数右边的数将只会在小于2的5次方以下,就是32以下才有效。因为Java中int类型是4个字节,也就是32位,左移超过32,其实等同于左移的减去32。比如数字2左移2位,和左移34位的结果是一致的。对长整型long来说,其实也是类似的,不过不是32,是64而已。
为了便于测试,我们下面的例子全都是使用8位来进行测试。
- 左位移(<<)
例如将数字2左移2位(以下首位是符号位):
2的二进制表示为:[0] 0000 0010 十进制:2
左移2位后的结果:[0] 0000 1000 十进制:8
-2的二进制表示为:
原码: [1] 0000 0010 补码:[1] 1111 1110
左移2位后的结果:
补码:[1] 1111 1000 原码:[1] 0000 1000
最终结果是:-8
这里简单说一点:正数的话,原码,反码,补码是一样的,而负数话,从补码求原码和从原码求补码是一样的,也就是说补码的补码还是码。 - 右移(>>)
同样,使用数字2来测试:
2的二进制表示为:[0] 0000 0010 十进制:2
右移2位后的结果:[0] 0000 0000 十进制:+0
-2的二进制表示为:
原码: [1] 0000 0010 补码:[1] 1111 1110
右移2位后的结果:
补码:[1] 1111 1111 原码:[1] 0000 0001
最终结果是:-1
这里也说一点,右移过程,首位补符号位,而左移,则是低位全部补0。 - 无符号右移(>>>)
同样,使用数字2来测试:
2的二进制表示为: [0] 0000 0010 十进制:2
无符号右移2位后的结果: 0000 0000 十进制:0
-2的二进制表示为:
原码: [1] 0000 0010 补码:[1] 1111 1110
无符号右移2位后的结果(这里因为int是32位,所以使用省略号了):
补码: 0011 … 1111 原码: 0011 … 1111
最终结果是:2的30次方-1,使用Windows计算器得出:1073741823
这里其实还要说一点,无符号右移,忽略符号位,首位补0。 - 按位与(&)
这次我们使用数字3和5,-3和-5,-3和5来测试:
3的二进制表示为: [0] 0000 0011
5的二进制表示为: [0] 0000 0101
进行逻辑与之后: [0]0000 0001 十进制:1
-3的二进制表示为:
原码: [1] 0000 0011 补码:[1] 1111 1101
-5的二进制表示为:
原码:[1] 0000 0101 补码: [1] 1111 1011
补码按位与的结果是:
补码:[1] 1111 1001 原码:[1] 0000 0111 十进制:-7
-3的二进制表示为:
原码: [1] 0000 0011 补码:[1] 1111 1101
5的二进制表示为: [0] 0000 0101
补码按位与计算的结果是:
补码:[0] 0000 0101 原码:[0] 0000 0101 十进制:5
这里还要说一点,符号位参与位运算。 - 按位或(|)
这次我们还是使用数字3和5来测试:
3的二进制表示为: [0] 0000 0011
5的二进制表示为: [0] 0000 0101
进行按位或之后: [0]0000 0111 十进制:7 - 按位非
将操作数的每一位都取反,包括符号位。
这次我们还是使用数字3来测试:
3的二进制表示为: [0] 0000 0011
进行按位非之后:
补码 [1]1111 1100 原码:[1]0000 0100
十进制:-4 - 按位异或(^)
这个简单来说,就是相同的为0,不同的为1,包括符号位。
这次我们使用数字-3和5来测试:
-3的二进制表示为:
原码: [1] 0000 0011 补码:[1] 1111 1101
5的二进制补码表示为: [0] 0000 0101
补码按位异或计算的结果是:
补码:[1] 1111 1000 原码:[1] 0000 1000 十进制:-8 - 以上测试我们都可以使用Integer.toBinaryString方法来查看元素的二进制形式,注:该方法返回的是元素的补码。