Android原始碼中的巧妙的位運算
與或非是啥?
常用的位運算子: “&” “|” “~”(與 或 非)。
1,“&”運算子的運算規則:兩個運算位同時為1時結果為“1”,否則為“0”。
如:1&0=0; 1&1=1; 0&0=0; 0&1=0;
2,“|”運算子的運算規則:兩個運算位只要有一個為“1”時結果為“1”,否則為“0”。
如:1|1=1; 1|0=1; 0|1=1; 0|0=0;
3,“~”運算子的運算規則:如果位為“0”,結果為“1”,如果位為“1”,結果為“0”
如:~0=1; ~1=0;
但是,在計算機中不是這樣的,結果為:
System.out.println("~0="+~0); 結果為:-1
System.out.println("~1="+~1); 結果為:-2
解析:這並不是計算機出問題了,而是計算機內部編碼的原因。
4,計算機內部編碼:
對於整數,計算機內部最高位表示符號位: 0為正 1為負。
對於負數,為了方便計算,計算機用補碼錶示其值。(原碼到補碼的轉換規則:除符號位外,原碼各位取反,然後加1得到補碼)。
解釋為啥~0=-1:
0在計算機中的二進位制形式: 0000 0000
0經過非運算(“~”)後: 1111 1111 (計算機中存的都是原碼)
反碼: 1000 0000
補碼: 1000 0001 (即:-1)
在Android中的應用
1,場景一:或運算子的使用
android:layout_gravity="bottom | right" 在這裡bottom和right在位上肯定是錯開的,這樣才能同時儲存該控價“居右”和“底部”的屬性。
//0x001=0000 0001
int right=0x001;
//0x002=0000 0010
int bottom=0x002;
//那麼 right|bottom= 0000 0011
上面的位錯開是為了或運算時,進行值的保留。這樣兩個狀態就能夠儲存在一個屬性裡面啦。
(暫時可以理解為將兩個狀態放在一個集合裡)
2,場景二:與運算的使用
上面介紹瞭如何組裝一個值。安卓原始碼中怎樣知道我們設定了right這個居右的狀態呢?這就需要“與”運算來取值。
int right=0x001;
int bottom=0x002;
int top=0x008;
int state=right | bottom;
system.out.println("是否存在right="+((state & right)==right));
system.out.println("是否存在top="+((state & top)==top));
//列印結果: 是否存在right=true; 是否存在top=false;
從上面程式碼可以清晰的看出,用“與”運算子可以取值 、判斷是否存在這個狀態。
(暫時可以理解成判斷某個狀態是不是在集合裡)、
3,場景三:非運算的使用
當我們想剔除集合中的一個狀態的時候要怎麼做呢? 用 “非”和“與”運算子聯合使用,如下程式碼。
int right=0x001; //1
int bottom=0x002; //2
int top=0x008; //8
int state=right | bottom; //3
System.out.println("剔除rightz狀態前"+state); //剔除rightz狀態前 3
state&=~right;
System.out.println("剔除rightz狀態後"+state); //剔除rightz狀態後 2
state&=~top;
System.out.println("剔除不存在的狀態top後"+state); //剔除不存在的狀態top後 2
如上就可以通過 “與” “非”的聯合運算實現剔除集合中狀態的功能。
總結:
或運算子整合值(組成狀態集合)
與運算子取值(集合中取出狀態)
與非剔除值(集合中移除狀態)