目錄:
一、前言
二、與或非是啥?
三、實戰
四、小結
五、寫在最後
一、前言
在檢視原始碼中,經常會看到很多這樣的符號“&
”、“|”、“~”,咋一看挺高大上;仔細一看,有點懵;再看看,其實就是大學學過的再普通不過的與、或、非。今天小盆友就以簡單的形式分享下,同時也是作為筆記記錄,等某天突然懵逼時可以回來看看,話不多說,開始擼。
二、與或非是啥?
或許,大學上的課,在還沒畢業時就還給老師了,所以我們先重溫下。
1、與運算子 &
知識點:兩位同時為“1”,結果才為“1”,否則為“0”。
運算規則:0&
0=0;
0&
1=0;
1&
0=0;
1&
1=1;
System.out.println("0 &
0" + (0 &
0));
System.out.println("0 &
1" + (0 &
1));
System.out.println("1 &
0" + (1 &
0));
System.out.println("1 &
1" + (1 &
1));
複製程式碼
其實就是運算的位要完全一樣,才保持原樣,否則就變為0。
2、或運算子 |
知識點:只要有一位為1,其值為1,否則位0。
運算規則:0|0=0; 0|1=1; 1|0=1; 1|1=1;
System.out.println("0 | 0 = " + (0 | 0));
System.out.println("0 | 1 = " + (0 | 1));
System.out.println("1 | 0 = " + (1 | 0));
System.out.println("1 | 1 = " + (1 | 1));
複製程式碼
其實就是隻要有1,結果就為1。
3、非運算子 ~
知識點:如果位為0,結果是1。如果位為1,結果是0
運算規則:~0=1; ~1=0;
System.out.println("~1 = " + ~(1));
System.out.println("~0 = " + ~(0));
複製程式碼
很驚喜!很意外!有沒有?!竟然不是0和1,這裡不是計算機出問題了,而是涉及到了計算機內部的編碼的問題,是不是想到了大學有一門課叫做《電腦科學導論》。詳細講解可以檢視這裡=>
傳送門為了方便檢視,我從文章截了一張圖
三、實戰
逼逼叨了這麼多,其實位運算子的文章很多,這裡其實還少了一個異或運算子,但因為沒有出現在實戰中,所以就不做多餘的操作了。我們來進行真正的運用吧。
1、場景一(或運算子的使用)
你有沒有在xml中這樣編寫過佈局
android:layout_gravity="bottom|right"複製程式碼
我們這裡就不用bottom、right在原始碼中真實的值,以方便講解
這裡的 bottom 和 right 在位上肯定是錯開的,這樣做位運算時,才能同時儲存該控制元件 “居右”和“底部” 的屬性。什麼叫位上錯開,且看下面程式碼。
// 0x001 = 0000 0001int right = 0x001;
// 0x001 = 0000 0010int bottom = 0x002;
// 結果 = 0000 0011 = 3System.out.println("right | bottom = " + (right | bottom));
複製程式碼
通過上面的程式碼,或許你已經恍然大悟(霧?),其實位錯開是為了或運算時,進行值的保留。 讓兩個狀態的能夠儲存在一個屬性中,或許你會問這樣有什麼好處了?我撓了下頭,想到了以下三個好處:
- 節省空間,避免不必要的屬性出現和維護成本(難道你想一個狀態用一個布林值來維護麼?手動譏諷,哈哈)
- 獲取方便,編碼簡潔
- 裝bi,不裝bi的程式設計師不是好的搬磚工
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));
複製程式碼
從上面的程式碼很清晰的看出,用 “與” 運算子進行 “取值”。是不是有點小驚喜呢?
3、場景三(非運算子的使用)
或許,你會有這樣的一個疑問,如果我想剔除當前已經包含的一個值,需要怎麼辦?這時候就是“非”和“與”運算子聯合使用的時候了,且看下面程式碼
int right = 0x001;
int bottom = 0x002;
int top = 0x008;
int state = right | bottom;
System.out.println("剔除 right 狀態前 " + state);
state &
= ~right;
System.out.println("剔除 right 狀態後 " + state);
state &
= ~top;
System.out.println("剔除不存在的 top 狀態 " + state);
System.out.println();
複製程式碼
是不是有點小激動了呢?哈哈,在安卓原始碼中運用挺多,舉個例子?,在ViewGroup中的requestDisallowInterceptTouchEvent方法便有用到,這裡就不一一列舉。敲黑板啦!!! 為什麼上面能做到剔除呢?小盆友手寫了下過程(多年沒寫字,不要噴,哈哈哈哈)
四、小結
- 或運算子整合值
- 與運算子取值
- 與非剔除值
五、寫在最後
或許還有很多更好玩的用法,但限於小盆友能力有限,文筆也一般般,所以就只能到這啦。如果您有更好或是更有趣的用法,或是本文有不妥之處,請與分享和糾正。編碼使我快樂,哈哈哈。