Java中的位运算,说实话,工作了两年的时间里,从来没有用过一次,因为平时都是些的是业务代码,很少接触比较底层的东西,我记得第一次在代码中看到还是在HashMap的Hash算法中看到的,这次重拾Java基础,着重理解了一下Java中的位运算,计算机中的运算一般都是操作反码进行运算,操作完成之后,再将结果的反码转化成原码,然后将二进制的结果转化成十进制输出出来,其实乘法和除法运算在计算机中都是通过位运算进行的,所以我觉得这部分应该好好整理一下,以下内容都是传智播客的Java基础中的讲解视频还有一些是讲解的课件、笔记中的内容,在此声明。
运算符 | 运算 | 位运算符的细节 |
<< | 左移 | 空位补0,被移除的高位丢失 |
>> | 右移 | 被移位的二进制最高位是0,右移后,空缺位补0,最高位是1,最高位补1 |
>>> | 无符号右移 | 被移位二进制无论是0或者1,空缺位都是用0补 |
& | 与运算 | 任何二进制位和0进行&运算,结果都是0,和1进行&运算,都是原值 |
| | 或运算 | 任何二进制位和0进行|运算,结果都是原值,和1进行|运算,都是1 |
^ | 异或运算 | 任何相同二进制位进行^运算,结果都是0,不同二进制位进行^运算,结果都是1 |
~ | 反码 |
注意:
<<:就是讲左边的操作数在内存中的二进制数据左移右边操作数指定的位数,右边被移空的位置补0。相当于乘以2的倍数
>>:右移稍微复杂一点,如果最高位是0,左边被移空的位就填入0,如果高位是1,左边被移空的位就填入1,相当于除以2的倍数
>>>:无论最高位是1还是0,左边被移空的高位都填入0
Java中运算符的优先级:(图片来源网路)
代码演示各种位运算:
1 /* 2 要做位运算,首先要把数据转换为二进制。 3 */ 4 public static void main(String[] args) { 5 //&,|,^,~ 6 int a = 3; 7 int b = 4; 8 9 System.out.println(3 & 4); 10 System.out.println(3 | 4); 11 System.out.println(3 ^ 4); 12 System.out.println(~3); 13 14 }
代码分析解读:
分析:因为是位运算,所以我们必须先把数据换算成二进制。
3的二进制:11
00000000 00000000 00000000 00000011
4的二进制:100
00000000 00000000 00000000 00000100
&位与运算:有0则0。
00000000 00000000 00000000 00000011
&00000000 00000000 00000000 00000100
-----------------------------------
00000000 00000000 00000000 00000000
结果是:0
|位或运算:有1则1。
00000000 00000000 00000000 00000011
|00000000 00000000 00000000 00000100
-----------------------------------
00000000 00000000 00000000 00000111
结果是:7
^位异或运算:相同则0,不同则1。
00000000 00000000 00000000 00000011
&00000000 00000000 00000000 00000100
-----------------------------------
00000000 00000000 00000000 00000111
结果是:7
~按位取反运算符:0变1,1变0
00000000 00000000 00000000 00000011
~11111111 11111111 11111111 11111100 (补码)
补码:11111111 11111111 11111111 11111100
反码:11111111 11111111 11111111 11111011
原码:10000000 00000000 00000000 00000100
结果是:-4
^异或运算的特点:
1 /* 2 ^的特点:一个数据对另一个数据位异或两次,该数本身不变。 3 */ 4 public static void main(String[] args) { 5 int a = 10; 6 int b = 20; 7 8 System.out.println(a ^ b ^ b); //10 9 System.out.println(a ^ b ^ a); //20 10 }
1 /* 2 <<:左移 左边最高位丢弃,右边补齐0 3 >>:右移 最高位是0,左边补齐0;最高为是1,左边补齐1 4 >>>:无符号右移 无论最高位是0还是1,左边补齐0 5 6 面试题: 7 请用最有效率的方式写出计算2乘以8的结果? 8 2 * 8 9 2 << 3 10 */ 11 public static void main(String[] args) { 12 //<< 把<<左边的数据乘以2的移动次幂 13 System.out.println(3 << 2); //3*2^2 = 3*4 = 12; 14 15 //>> 把>>左边的数据除以2的移动次幂 16 System.out.println(24 >> 2); //24 / 2^2 = 24 / 4 = 6 17 System.out.println(24 >>> 2); 18 19 System.out.println(-24 >> 2); 20 System.out.println(-24 >>> 2); 21 }
代码分析解读(32位):
计算出3的二进制:11
00000000 00000000 00000000 00000011
(00)000000 00000000 00000000 0000001100
>>(右移)的移动:
计算出-24的二进制:11000
原码:10000000 00000000 00000000 00011000
反码:11111111 11111111 11111111 11100111
补码:11111111 11111111 11111111 11101000
11111111 11111111 11111111 11101000
1111111111 11111111 11111111 111010(00) 补码
补码:1111111111 11111111 11111111 111010
反码:1111111111 11111111 11111111 111001
原码:1000000000 00000000 00000000 000110
结果:-6
>>>(无符号右移)的移动:
计算出-24的二进制:11000
原码:10000000 00000000 00000000 00011000
反码:11111111 11111111 11111111 11100111
补码:11111111 11111111 11111111 11101000
11111111 11111111 11111111 11101000
0011111111 11111111 11111111 111010(00)
结果:1073741818