android位運算講解與實戰

猛猛的小盆友發表於2019-01-05

目錄:
一、前言
二、與或非是啥?
三、實戰
四、小結
五、寫在最後

一、前言

在檢視原始碼中,經常會看到很多這樣的符號“&”、“|”、“~”,咋一看挺高大上;仔細一看,有點懵;再看看,其實就是大學學過的再普通不過的與、或、非。今天小盆友就以簡單的形式分享下,同時也是作為筆記記錄,等某天突然懵逼時可以回來看看,話不多說,開始擼。

二、與或非是啥?

或許,大學上的課,在還沒畢業時就還給老師了,所以我們先重溫下。

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,這裡不是計算機出問題了,而是涉及到了計算機內部的編碼的問題,是不是想到了大學有一門課叫做《電腦科學導論》。詳細講解可以檢視這裡=>傳送門為了方便檢視,我從文章截了一張圖

image

三、實戰

逼逼叨了這麼多,其實位運算子的文章很多,這裡其實還少了一個異或運算子,但因為沒有出現在實戰中,所以就不做多餘的操作了。我們來進行真正的運用吧。

1、場景一(或運算子的使用)

你有沒有在xml中這樣編寫過佈局

android:layout_gravity="bottom|right"
複製程式碼

我們這裡就不用bottom、right在原始碼中真實的值,以方便講解

這裡的 bottom 和 right 在位上肯定是錯開的,這樣做位運算時,才能同時儲存該控制元件 “居右”和“底部” 的屬性。 什麼叫位上錯開,且看下面程式碼。

// 0x001 = 0000 0001
int right = 0x001;
// 0x001 = 0000 0010
int bottom = 0x002;
// 結果 = 0000 0011 = 3
System.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方法便有用到,這裡就不一一列舉。 敲黑板啦!!! 為什麼上面能做到剔除呢?小盆友手寫了下過程(多年沒寫字,不要噴,哈哈哈哈)

手寫過程

四、小結

  • 或運算子整合值
  • 與運算子取值
  • 與非剔除值

五、寫在最後

或許還有很多更好玩的用法,但限於小盆友能力有限,文筆也一般般,所以就只能到這啦。如果您有更好或是更有趣的用法,或是本文有不妥之處,請與分享和糾正。編碼使我快樂,哈哈哈。

如果需要更多的交流與探討,可以通過以下微信二維碼加小盆友好友。

android位運算講解與實戰

相關文章