前言
我们可能经常看到以下这样的代码,看得真是云里雾里。 下面我们来学习一下这些符号,它们是如何工作的吧。
读写锁中源码
线程池中源码
这里涉及到一些二进制的知识。
下面正式开始吧!
介绍以下运算符计算
~ & ^ |
这里用int来计算, 然而int 为32位(具体可以Integer.SIZE,Long为64位。)。让我们逐个击破吧!
& 与运算
&与运算 ,两个操作数中位都为1,结果才为1,否则结果为0,
1 | int a=129;//10000001 |
运行结果
二进制 129 : 10000001
二进制 127 : 1111111
二进制 -2 : 11111111111111111111111111111110
&与运算:1
&与运算:128
&与运算:126
来详细计算一下,再下面的例子就不详细计算了,因为计算方式都是类似的。 二进制 129 : 10000001,这里是要补够32位。(int为32位)
下面是129 & 127
敲重点 按照&与运算 ,两个操作数中位都为1,结果才为1,否则结果为0。 正数前面补0,,负数前面补1,补够32位,下面的例子会详细展开负数的计算。
00000000000000000000000010000001
00000000000000000000000001111111
00000000000000000000000000000001 //这个为结果,结果为1.
129 & -2
负数的补码计算方式特别一些。
符号位是表示最高那一位,就是左边第一位。比如01111111 ,这里的0就是最高位。
⑴如果补码的符号位为“0”,表示是一个正数,其原码就是补码。
⑵如果补码的符号位为“1”,表示是一个负数,那么求给定的这个补码的补码就是要求的原码。
我们来算算-2的补码吧。
2 的二进制是 00000000000000000000000000000010
第一步 取反 11111111111111111111111111111101
第二步 加1 得 11111111111111111111111111111110 //-2的补码
00000000000000000000000010000001
11111111111111111111111111111110
00000000000000000000000010000000 //这个为结果,结果为128.
| 或运算符
两个位只要有一个为1,那么结果就是1,否则就为0。
1 | //或运算符用符号“|” |
运行结果
注意:高位为1,即负数。结果要保留高位,其他取反,加一。得到结果。
1 |
|
~ 非运算符
非运算符用符号“~”表示,其运算规律如下:
如果位为0,结果是1,如果位为1,结果是0
1 |
|
运行结果
1 |
|
~非详细计算例子
注意这个是人工的计算方式:
二进制 129:
00000000000000000000000010000001
第一步取反,结果得: 11111111111111111111111101111110 //这个机器会直接输出-130,像下面这样
//0b代表二进制
System.out.println(“~129:”+0b11111111111111111111111101111110);
简单来说就是 129+1=130,取反,变负数,-130。
简单来说就是 -3+1=-2,取反,变正数,2。
那结果11111111111111111111111101111110,是怎么转换成-130的呢?
人工计算一下。
第一步,保留高位符号,其他去反,
得: 10000000000000000000000010000001
加一 10000000000000000000000010000010
高位不参与计算,得出结果就130,由于高位是1,为负数,得-130。
^异或运算符
异或运算符是用符号“^”表示的,其运算规律是:
两个操作数的位中,相同则结果为0,不同则结果为1
1 |
|
运行结果
1 | ^异或运算 129 ^ 2 : 131 |
运算符 << , >> , >>>
<< | 左移运算符,将运算符左边的对象向左移动运算符右边指定的位数(在低位补0) x<<3 |
> > | “有符号”右移运算 符,将运算符左边的对象向右移动运算符右边指定的位数。使用符号扩展机制,也就是说,如果值为正,则在高位补0,如果值为负,则在高位补1.x>>3 |
> > > | “无符号”右移运算 符,将运算符左边的对象向右移动运算符右边指定的位数。采用0扩展机制,也就是说,无论值的正负,都在高位补0. |
1 |
|
运行结果
1 | <<:16 |
总结
本人知识有限,如有描述错误之处,愿虎正。
你看这个像不像你欠我的赞。
谢谢大家。
你的赞就像冬日暖阳,温暖心窝。